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

Raymond Knopp's avatar
 
Raymond Knopp committed
28
*******************************************************************************/
29 30

/*! \file lte-softmodem.c
Raymond Knopp's avatar
 
Raymond Knopp committed
31
 * \brief main program to control HW and scheduling
32
 * \author R. Knopp, F. Kaltenberger, Navid Nikaein
Raymond Knopp's avatar
 
Raymond 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
Raymond Knopp's avatar
 
Raymond Knopp committed
37 38 39
 * \note
 * \warning
 */
Raymond Knopp's avatar
 
Raymond 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 53 54
#include <signal.h>
#include <execinfo.h>
#include <getopt.h>

#include "rt_wrapper.h"
55 56
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all

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

#ifdef EMOS
#include <gps.h>
jiangx's avatar
jiangx committed
62
struct gps_fix_t dummy_gps_data;
63 64 65
#endif

#include "PHY/types.h"
66

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

71
#ifdef EXMIMO
72
#include "openair0_lib.h"
Raymond Knopp's avatar
 
Raymond Knopp committed
73 74 75 76
#else
#include "../../ARCH/COMMON/common_lib.h"
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
77
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
78 79 80

#include "PHY/vars.h"
#include "MAC_INTERFACE/vars.h"
81
//#include "SCHED/defs.h"
82 83 84 85 86 87 88 89 90 91 92 93
#include "SCHED/vars.h"
#include "LAYER2/MAC/vars.h"

#include "../../SIMU/USER/init_lte.h"

#ifdef EMOS
#include "SCHED/phy_procedures_emos.h"
#endif

#ifdef OPENAIR2
#include "LAYER2/MAC/defs.h"
#include "LAYER2/MAC/vars.h"
94
#include "LAYER2/MAC/proto.h"
95 96 97 98 99 100 101 102 103
#include "RRC/LITE/vars.h"
#include "PHY_INTERFACE/vars.h"
#endif

#ifdef SMBV
#include "PHY/TOOLS/smbv.h"
unsigned short config_frames[4] = {2,9,11,13};
#endif
#include "UTIL/LOG/log_extern.h"
Navid Nikaein's avatar
Navid Nikaein committed
104
#include "UTIL/OTG/otg_tx.h"
105
#include "UTIL/OTG/otg_externs.h"
106 107
#include "UTIL/MATH/oml.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
108
#include "UTIL/OPT/opt.h"
109
#include "enb_config.h"
Navid Nikaein's avatar
Navid Nikaein committed
110
//#include "PHY/TOOLS/time_meas.h"
111

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
112 113 114 115
#ifndef OPENAIR2
#include "UTIL/OTG/otg_vars.h"
#endif

116 117
#if defined(ENABLE_ITTI)
# include "intertask_interface_init.h"
118
# include "create_tasks.h"
119 120
# if defined(ENABLE_USE_MME)
#   include "s1ap_eNB.h"
121
#ifdef PDCP_USE_NETLINK
122 123
#   include "SIMULATION/ETH_TRANSPORT/proto.h"
#endif
124
# endif
125 126
#endif

127 128 129
#ifdef XFORMS
#include "PHY/TOOLS/lte_phy_scope.h"
#include "stats.h"
130 131 132 133 134
#endif

#define FRAME_PERIOD    100000000ULL
#define DAQ_PERIOD      66667ULL

Florian Kaltenberger's avatar
Florian Kaltenberger committed
135
//#define DEBUG_THREADS 1
Raymond Knopp's avatar
 
Raymond Knopp committed
136

Raymond Knopp's avatar
 
Raymond Knopp committed
137 138
//#define USRP_DEBUG 1

139
struct timing_info_t {
140 141 142 143
  //unsigned int frame, hw_slot, last_slot, next_slot;
  RTIME time_min, time_max, time_avg, time_last, time_now;
  //unsigned int mbox0, mbox1, mbox2, mbox_target;
  unsigned int n_samples;
144 145 146
} timing_info;


Raymond Knopp's avatar
 
Raymond Knopp committed
147

148
openair0_config_t openair0_cfg[MAX_CARDS];
Raymond Knopp's avatar
 
Raymond Knopp committed
149

Raymond Knopp's avatar
 
Raymond Knopp committed
150 151
int32_t **rxdata;
int32_t **txdata;
152 153
int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]);
int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]);
154

155 156 157 158
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]
double cpuf;

159
void fill_ue_band_info(void);
160
#ifdef XFORMS
161
// current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0)
162
// at eNB 0, an UL scope for every UE
163
FD_lte_phy_scope_ue  *form_ue[NUMBER_OF_UE_MAX];
164
FD_lte_phy_scope_enb *form_enb[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
165
FD_stats_form                  *form_stats=NULL,*form_stats_l2=NULL;
166
char title[255];
167
unsigned char                   scope_enb_num_ue = 1;
168 169 170
#endif //XFORMS

#ifdef RTAI
171

172 173
static long                      main_eNB_thread;
static long                      main_ue_thread;
174

175
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
176 177
pthread_t                       main_eNB_thread;
pthread_t                       main_ue_thread;
178

179
pthread_attr_t                  attr_dlsch_threads;
180 181
pthread_attr_t                  attr_UE_thread;

182
#ifndef LOWLATENCY
183
struct sched_param              sched_param_dlsch;
184
#endif
185
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
186

Raymond Knopp's avatar
 
Raymond Knopp committed
187 188
pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex;
189
int sync_var=-1; //!< protected by mutex \ref sync_mutex.
190

191

192 193


194
struct sched_param              sched_param_UE_thread;
195

196 197
pthread_attr_t                  attr_eNB_proc_tx[MAX_NUM_CCs][NUM_ENB_THREADS];
pthread_attr_t                  attr_eNB_proc_rx[MAX_NUM_CCs][NUM_ENB_THREADS];
198
#ifndef LOWLATENCY
199 200
struct sched_param              sched_param_eNB_proc_tx[MAX_NUM_CCs][NUM_ENB_THREADS];
struct sched_param              sched_param_eNB_proc_rx[MAX_NUM_CCs][NUM_ENB_THREADS];
201
#endif
202
#ifdef XFORMS
Raymond Knopp's avatar
 
Raymond Knopp committed
203
static pthread_t                forms_thread; //xforms
204 205 206
#endif
#ifdef EMOS
static pthread_t                thread3; //emos
jiangx's avatar
jiangx committed
207
static pthread_t                thread4; //GPS
208
#endif
209

Raymond Knopp's avatar
 
Raymond Knopp committed
210
openair0_device openair0;
211

Raymond Knopp's avatar
 
Raymond Knopp committed
212

213
/*
Raymond Knopp's avatar
 
Raymond Knopp committed
214 215 216
  static int instance_cnt=-1; //0 means worker is busy, -1 means its free
  int instance_cnt_ptr_kern,*instance_cnt_ptr_user;
  int pci_interface_ptr_kern;
217 218 219 220
*/
//extern unsigned int bigphys_top;
//extern unsigned int mem_base;

221
//int                             card = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
222

223

224
#if defined(ENABLE_ITTI)
225 226
static volatile int             start_eNB = 0;
static volatile int             start_UE = 0;
227
#endif
228 229 230 231 232 233
volatile int                    oai_exit = 0;

//static int                      time_offset[4] = {-138,-138,-138,-138};
//static int                      time_offset[4] = {-145,-145,-145,-145};
static int                      time_offset[4] = {0,0,0,0};

Raymond Knopp's avatar
 
Raymond Knopp committed
234

235
static char                     UE_flag=0;
236 237
//static uint8_t                  eNB_id=0,UE_id=0;

238
static char                     threequarter_fs=0;
239

240
uint32_t                 downlink_frequency[MAX_NUM_CCs][4];
241
int32_t                  uplink_frequency_offset[MAX_NUM_CCs][4];
Lionel Gauthier's avatar
Lionel Gauthier committed
242

243
openair0_rf_map rf_map[MAX_NUM_CCs];
244

245
static char                    *conf_config_file_name = NULL;
246
#if defined(ENABLE_ITTI)
247
static char                    *itti_dump_file = NULL;
Raymond Knopp's avatar
 
Raymond Knopp committed
248 249
#endif

250
int UE_scan = 1;
251
int UE_scan_carrier = 0;
252 253
runmode_t mode = normal_txrx;

254 255
FILE *input_fd=NULL;

256

Raymond Knopp's avatar
 
Raymond Knopp committed
257
#ifdef EXMIMO
258 259 260 261
#if MAX_NUM_CCs == 1
double tx_gain[MAX_NUM_CCs][4] = {{20,20,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{20,20,0,0}};
#else
262 263
double tx_gain[MAX_NUM_CCs][4] = {{20,20,0,0},{20,20,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{20,20,0,0},{20,20,0,0}};
264
#endif
265
// these are for EXMIMO2 target only
266
/*
Raymond Knopp's avatar
 
Raymond Knopp committed
267 268 269
  static unsigned int             rxg_max[4] =    {133,133,133,133};
  static unsigned int             rxg_med[4] =    {127,127,127,127};
  static unsigned int             rxg_byp[4] =    {120,120,120,120};
270
 */
271
// these are for EXMIMO2 card 39
272 273 274 275 276 277
unsigned int             rxg_max[4] =    {128,128,128,126};
unsigned int             rxg_med[4] =    {122,123,123,120};
unsigned int             rxg_byp[4] =    {116,117,116,116};
unsigned int             nf_max[4] =    {7,9,16,12};
unsigned int             nf_med[4] =    {12,13,22,17};
unsigned int             nf_byp[4] =    {15,20,29,23};
278 279 280
#if MAX_NUM_CCs == 1
rx_gain_t                rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain}};
#else
281
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}};
282
#endif
Lionel Gauthier's avatar
Lionel Gauthier committed
283
#else
kortke's avatar
kortke committed
284 285
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0}};
Lionel Gauthier's avatar
Lionel Gauthier committed
286
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
287

Raymond Knopp's avatar
 
Raymond Knopp committed
288
double sample_rate=30.72e6;
289
double bw = 10.0e6;
290

291
static int                      tx_max_power[MAX_NUM_CCs]; /* =  {0,0}*/;
292

Florian Kaltenberger's avatar
Florian Kaltenberger committed
293 294
int chain_offset=0;

295
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
296 297 298 299
char ref[128] = "internal";
char channels[128] = "0";

#endif
300 301

int                      rx_input_level_dBm;
302
static int                      online_log_messages=0;
303
#ifdef XFORMS
304
extern int                      otg_enabled;
305
static char                     do_forms=0;
306
#else
307
int                             otg_enabled;
308
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
309
//int                             number_of_cards =   1;
Raymond Knopp's avatar
 
Raymond Knopp committed
310
#ifdef EXMIMO
311 312
static int                      mbox_bounds[20] =   {8,16,24,30,38,46,54,60,68,76,84,90,98,106,114,120,128,136,144, 0}; ///boundaries of slots in terms ob mbox counter rounded up to even numbers
//static int                      mbox_bounds[20] =   {6,14,22,28,36,44,52,58,66,74,82,88,96,104,112,118,126,134,142, 148}; ///boundaries of slots in terms ob mbox counter rounded up to even numbers
Raymond Knopp's avatar
 
Raymond Knopp committed
313
#endif
314

Raymond Knopp's avatar
 
Raymond Knopp committed
315
static LTE_DL_FRAME_PARMS      *frame_parms[MAX_NUM_CCs];
316

Raymond Knopp's avatar
 
Raymond Knopp committed
317
int multi_thread=1;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
318
uint32_t target_dl_mcs = 28; //maximum allowed mcs
319
uint32_t target_ul_mcs = 10;
320
uint32_t timing_advance = 0;
321 322
uint8_t exit_missed_slots=1;
uint64_t num_missed_slots=0; // counter for the number of missed slots
323

Raymond Knopp's avatar
 
Raymond Knopp committed
324

325
time_stats_t softmodem_stats_mt; // main thread
Raymond Knopp's avatar
 
Raymond Knopp committed
326
time_stats_t softmodem_stats_hw; //  hw acquisition
327 328
time_stats_t softmodem_stats_tx_sf[10]; // total tx time
time_stats_t softmodem_stats_rx_sf[10]; // total rx time
Navid Nikaein's avatar
Navid Nikaein committed
329 330
void reset_opp_meas(void);
void print_opp_meas(void);
331
int transmission_mode=1;
Raymond Knopp's avatar
 
Raymond Knopp committed
332

333
int16_t           glog_level         = LOG_INFO;
Lionel Gauthier's avatar
 
Lionel Gauthier committed
334
int16_t           glog_verbosity     = LOG_MED;
335
int16_t           hw_log_level       = LOG_INFO;
Lionel Gauthier's avatar
 
Lionel Gauthier committed
336
int16_t           hw_log_verbosity   = LOG_MED;
337
int16_t           phy_log_level      = LOG_INFO;
Lionel Gauthier's avatar
 
Lionel Gauthier committed
338
int16_t           phy_log_verbosity  = LOG_MED;
339
int16_t           mac_log_level      = LOG_INFO;
Lionel Gauthier's avatar
 
Lionel Gauthier committed
340
int16_t           mac_log_verbosity  = LOG_MED;
341
int16_t           rlc_log_level      = LOG_INFO;
Lionel Gauthier's avatar
 
Lionel Gauthier committed
342
int16_t           rlc_log_verbosity  = LOG_MED;
343
int16_t           pdcp_log_level     = LOG_INFO;
Lionel Gauthier's avatar
 
Lionel Gauthier committed
344
int16_t           pdcp_log_verbosity = LOG_MED;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
345
int16_t           rrc_log_level      = LOG_INFO;
Lionel Gauthier's avatar
 
Lionel Gauthier committed
346
int16_t           rrc_log_verbosity  = LOG_MED;
347 348 349
int16_t           opt_log_level      = LOG_INFO;
int16_t           opt_log_verbosity  = LOG_MED;

Lionel Gauthier's avatar
 
Lionel Gauthier committed
350 351 352 353 354 355
# 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
356 357 358
#if defined (ENABLE_SECURITY)
int16_t           osa_log_level      = LOG_INFO;
int16_t           osa_log_verbosity  = LOG_MED;
359
#endif
360

Raymond Knopp's avatar
 
Raymond Knopp committed
361 362

#ifdef ETHERNET
363 364
char *rrh_UE_ip = "127.0.0.1";
int rrh_UE_port = 51000;
Raymond Knopp's avatar
 
Raymond Knopp committed
365
#endif
366 367 368 369 370 371

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

Raymond Knopp's avatar
 
Raymond Knopp committed
372
char uecap_xer[1024],uecap_xer_in=0;
373 374
extern void *UE_thread(void *arg);
extern void init_UE_threads(void);
Raymond Knopp's avatar
 
Raymond Knopp committed
375

376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416
/*---------------------BMC: timespec helpers -----------------------------*/

struct timespec min_diff_time = { .tv_sec = 0, .tv_nsec = 0 };
struct timespec max_diff_time = { .tv_sec = 0, .tv_nsec = 0 };

struct timespec clock_difftime(struct timespec start, struct timespec end)
{
    struct timespec temp;
    if ((end.tv_nsec-start.tv_nsec)<0) {
        temp.tv_sec = end.tv_sec-start.tv_sec-1;
	temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
    } else {
        temp.tv_sec = end.tv_sec-start.tv_sec;
	temp.tv_nsec = end.tv_nsec-start.tv_nsec;
    }
    return temp;
}

void print_difftimes()
{
#ifdef DEBUG
    printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
#else
    LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
#endif
}

void update_difftimes(struct timespec start, struct timespec end)
{
    struct timespec diff_time = { .tv_sec = 0, .tv_nsec = 0 };
    int             changed = 0;
    diff_time = clock_difftime(start, end);
    if ((min_diff_time.tv_nsec == 0) || (diff_time.tv_nsec < min_diff_time.tv_nsec)) { min_diff_time.tv_nsec = diff_time.tv_nsec; changed = 1; }
    if ((max_diff_time.tv_nsec == 0) || (diff_time.tv_nsec > max_diff_time.tv_nsec)) { max_diff_time.tv_nsec = diff_time.tv_nsec; changed = 1; }
#if 1
    if (changed) print_difftimes();
#endif
}

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

417
unsigned int build_rflocal(int txi, int txq, int rxi, int rxq)
418
{
Raymond Knopp's avatar
 
Raymond Knopp committed
419
  return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
420 421 422
}
unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
423
  return (dcoff_i_rxfe + (dcoff_q_rxfe<<8));
424 425
}

426
#if !defined(ENABLE_ITTI)
427 428 429 430 431 432 433 434
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);
435

436 437 438 439
    // print out all the frames to stderr
    fprintf(stderr, "Error: signal %d:\n", sig);
    backtrace_symbols_fd(array, size, 2);
    exit(-1);
440 441
  } else {
    printf("trying to exit gracefully...\n");
442
    oai_exit = 1;
443 444
  }
}
445
#endif
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
#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");
  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");
Raymond Knopp's avatar
 
Raymond Knopp committed
461 462
  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");
463
  printf("  --no-L2-connect bypass L2 and upper layers\n");
464 465 466 467
  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");
468
  printf("  -C Set the downlink frequency for all component carriers\n");
469 470 471 472 473 474 475 476 477
  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");
  printf("  -G Set the global log level \n");
  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
478
  printf("  -r Set the PRB, valid values: 6, 25, 50, 100  \n");    
479 480
  printf("  -S Skip the missed slots/subframes \n");    
  printf("  -t Set the maximum uplink MCS\n");
481
  printf("  -T Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n");
482 483 484 485
  printf("  -U Set the lte softmodem as a UE\n");
  printf("  -W Enable L2 wireshark messages on localhost \n");
  printf("  -V Enable VCD (generated file will be located atopenair_dump_eNB.vcd, read it with target/RT/USER/eNB.gtkw\n");
  printf("  -x Set the transmission mode, valid options: 1 \n"RESET);    
486

487
}
488 489
void exit_fun(const char* s)
{
490
  if (s != NULL) {
491
    printf("%s %s() Exiting OAI softmodem: %s\n",__FILE__, __FUNCTION__, s);
492 493 494 495 496
  }

  oai_exit = 1;

#if defined(ENABLE_ITTI)
Florian Kaltenberger's avatar
Florian Kaltenberger committed
497
  sleep(1); //allow lte-softmodem threads to exit first
498
  itti_terminate_tasks (TASK_UNKNOWN);
499
#endif
500 501 502 503 504 505

  //rt_sleep_ns(FRAME_PERIOD);

  //exit (-1);
}

506

507
#ifdef XFORMS
508

509 510
void reset_stats(FL_OBJECT *button, long arg)
{
511 512
  int i,j,k;
  PHY_VARS_eNB *phy_vars_eNB = PHY_vars_eNB_g[0][0];
513 514 515 516 517 518 519

  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_eNB[i][0]->Mdlharq; j++) {
        phy_vars_eNB->eNB_UE_stats[i].dlsch_NAK[k][j]=0;
        phy_vars_eNB->eNB_UE_stats[i].dlsch_ACK[k][j]=0;
        phy_vars_eNB->eNB_UE_stats[i].dlsch_trials[k][j]=0;
520
      }
521

522 523 524
      phy_vars_eNB->eNB_UE_stats[i].dlsch_l2_errors[k]=0;
      phy_vars_eNB->eNB_UE_stats[i].ulsch_errors[k]=0;
      phy_vars_eNB->eNB_UE_stats[i].ulsch_consecutive_errors=0;
525 526 527 528 529 530

      for (j=0; j<phy_vars_eNB->ulsch_eNB[i]->Mdlharq; j++) {
        phy_vars_eNB->eNB_UE_stats[i].ulsch_decoding_attempts[k][j]=0;
        phy_vars_eNB->eNB_UE_stats[i].ulsch_decoding_attempts_last[k][j]=0;
        phy_vars_eNB->eNB_UE_stats[i].ulsch_round_errors[k][j]=0;
        phy_vars_eNB->eNB_UE_stats[i].ulsch_round_fer[k][j]=0;
531
      }
532
    }
533

534 535 536
    phy_vars_eNB->eNB_UE_stats[i].dlsch_sliding_cnt=0;
    phy_vars_eNB->eNB_UE_stats[i].dlsch_NAK_round0=0;
    phy_vars_eNB->eNB_UE_stats[i].dlsch_mcs_offset=0;
537 538 539
  }
}

540 541
static void *scope_thread(void *arg)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
542
  char stats_buffer[16384];
543
# ifdef ENABLE_XFORMS_WRITE_STATS
Raymond Knopp's avatar
 
Raymond Knopp committed
544
  FILE *UE_stats, *eNB_stats;
545
# endif
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
546
  int len = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
547
  struct sched_param sched_param;
548
  int UE_id, CC_id;
549

550
  sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
Raymond Knopp's avatar
 
Raymond Knopp committed
551
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
552

Raymond Knopp's avatar
 
Raymond Knopp committed
553
  printf("Scope thread has priority %d\n",sched_param.sched_priority);
554

555
# ifdef ENABLE_XFORMS_WRITE_STATS
556 557

  if (UE_flag==1)
Raymond Knopp's avatar
 
Raymond Knopp committed
558
    UE_stats  = fopen("UE_stats.txt", "w");
559
  else
Raymond Knopp's avatar
 
Raymond Knopp committed
560
    eNB_stats = fopen("eNB_stats.txt", "w");
561

562
#endif
563

Raymond Knopp's avatar
 
Raymond Knopp committed
564 565
  while (!oai_exit) {
    if (UE_flag==1) {
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
566
      len = dump_ue_stats (PHY_vars_UE_g[0][0], stats_buffer, 0, mode,rx_input_level_dBm);
knopp's avatar
knopp committed
567 568 569
      //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);
570

571 572 573 574 575
      phy_scope_UE(form_ue[0],
                   PHY_vars_UE_g[0][0],
                   0,
                   0,7);

Raymond Knopp's avatar
 
Raymond Knopp committed
576
    } else {
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
577 578
#ifdef OPENAIR2
      len = dump_eNB_l2_stats (stats_buffer, 0);
knopp's avatar
knopp committed
579 580 581
      //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
582 583
#endif
      len = dump_eNB_stats (PHY_vars_eNB_g[0][0], stats_buffer, 0);
584

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

588 589 590
      //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);
591

592
      for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
593 594 595 596 597
	for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
	  phy_scope_eNB(form_enb[CC_id][UE_id],
			PHY_vars_eNB_g[0][CC_id],
			UE_id);
	}
Raymond Knopp's avatar
 
Raymond Knopp committed
598
      }
599

600
    }
601

Raymond Knopp's avatar
 
Raymond Knopp committed
602
    //printf("doing forms\n");
Florian Kaltenberger's avatar
Florian Kaltenberger committed
603 604
    //usleep(100000); // 100 ms
    sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
605
  }
606

607
  //  printf("%s",stats_buffer);
608

609
# ifdef ENABLE_XFORMS_WRITE_STATS
610

611 612 613 614 615 616
  if (UE_flag==1) {
    if (UE_stats) {
      rewind (UE_stats);
      fwrite (stats_buffer, 1, len, UE_stats);
      fclose (UE_stats);
    }
617
  } else {
618 619 620 621 622 623
    if (eNB_stats) {
      rewind (eNB_stats);
      fwrite (stats_buffer, 1, len, eNB_stats);
      fclose (eNB_stats);
    }
  }
624

625
# endif
626

Raymond Knopp's avatar
 
Raymond Knopp committed
627
  pthread_exit((void*)arg);
628 629 630 631 632 633
}
#endif

#ifdef EMOS
#define NO_ESTIMATES_DISK 100 //No. of estimates that are aquired before dumped to disk

jiangx's avatar
jiangx committed
634 635 636 637 638 639 640 641
void* gps_thread (void *arg)
{

  struct gps_data_t gps_data;
  struct gps_data_t *gps_data_ptr = &gps_data;
  struct sched_param sched_param;
  int ret;

642
  sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
jiangx's avatar
jiangx committed
643
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
644

jiangx's avatar
jiangx committed
645 646 647
  printf("GPS thread has priority %d\n",sched_param.sched_priority);

  memset(&dummy_gps_data,0,sizeof(struct gps_fix_t));
648

jiangx's avatar
jiangx committed
649 650
#if GPSD_API_MAJOR_VERSION>=5
  ret = gps_open("127.0.0.1","2947",gps_data_ptr);
651

jiangx's avatar
jiangx committed
652 653 654
  if (ret!=0)
#else
  gps_data_ptr = gps_open("127.0.0.1","2947");
655 656

  if (gps_data_ptr == NULL)
jiangx's avatar
jiangx committed
657
#endif
658 659 660 661 662
  {
    printf("[EMOS] Could not open GPS\n");
    pthread_exit((void*)arg);
  }

jiangx's avatar
jiangx committed
663 664 665 666 667
#if GPSD_API_MAJOR_VERSION>=4
  else if (gps_stream(gps_data_ptr, WATCH_ENABLE,NULL) != 0)
#else
  else if (gps_query(gps_data_ptr, "w+x") != 0)
#endif
668 669 670 671
  {
    printf("[EMOS] Error sending command to GPS\n");
    pthread_exit((void*) arg);
  } else
jiangx's avatar
jiangx committed
672 673
    printf("[EMOS] Opened GPS, gps_data=%p\n", gps_data_ptr);

674 675 676

  while (!oai_exit) {
    printf("[EMOS] polling data from gps\n");
jiangx's avatar
jiangx committed
677
#if GPSD_API_MAJOR_VERSION>=5
678 679 680

    if (gps_waiting(gps_data_ptr,500)) {
      if (gps_read(gps_data_ptr) <= 0) {
jiangx's avatar
jiangx committed
681
#else
682 683 684 685 686 687 688 689

    if (gps_waiting(gps_data_ptr)) {
      if (gps_poll(gps_data_ptr) != 0) {
#endif
        printf("[EMOS] problem polling data from gps\n");
      } else {
        memcpy(&dummy_gps_data,&(gps_data_ptr->fix),sizeof(struct gps_fix_t));
        printf("[EMOS] lat %g, lon %g\n",gps_data_ptr->fix.latitude,gps_data_ptr->fix.longitude);
jiangx's avatar
jiangx committed
690
      }
691 692 693 694 695 696 697 698
    } //gps_waiting
    else {
      printf("[EMOS] WARNING: No GPS data available, storing dummy packet\n");
    }

    //rt_sleep_ns(1000000000LL);
    sleep(1);
  } //oai_exit
jiangx's avatar
jiangx committed
699 700 701 702 703

  pthread_exit((void*) arg);

}

704 705 706 707 708 709 710 711 712 713 714
void *emos_thread (void *arg)
{
  char c;
  char *fifo2file_buffer, *fifo2file_ptr;

  int fifo, counter=0, bytes;

  FILE  *dumpfile_id;
  char  dumpfile_name[1024];
  time_t starttime_tmp;
  struct tm starttime;
715

jiangx's avatar
jiangx committed
716
  int channel_buffer_size,ret;
717

718 719 720
  time_t timer;
  struct tm *now;

721
  struct sched_param sched_param;
722 723

  sched_param.sched_priority = sched_get_priority_max(SCHED_FIFO)-1;
724
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
725

726
  printf("EMOS thread has priority %d\n",sched_param.sched_priority);
727

728 729 730 731 732 733 734 735 736 737 738 739
  timer = time(NULL);
  now = localtime(&timer);

  if (UE_flag==0)
    channel_buffer_size = sizeof(fifo_dump_emos_eNB);
  else
    channel_buffer_size = sizeof(fifo_dump_emos_UE);

  // allocate memory for NO_FRAMES_DISK channes estimations
  fifo2file_buffer = malloc(NO_ESTIMATES_DISK*channel_buffer_size);
  fifo2file_ptr = fifo2file_buffer;

740 741 742 743
  if (fifo2file_buffer == NULL) {
    printf("[EMOS] Cound not allocate memory for fifo2file_buffer\n");
    exit(EXIT_FAILURE);
  }
744

745 746 747 748
  if ((fifo = open(CHANSOUNDER_FIFO_DEV, O_RDONLY)) < 0) {
    fprintf(stderr, "[EMOS] Error opening the fifo\n");
    exit(EXIT_FAILURE);
  }
749 750 751 752 753


  time(&starttime_tmp);
  localtime_r(&starttime_tmp,&starttime);
  snprintf(dumpfile_name,1024,"/tmp/%s_data_%d%02d%02d_%02d%02d%02d.EMOS",
754 755
           (UE_flag==0) ? "eNB" : "UE",
           1900+starttime.tm_year, starttime.tm_mon+1, starttime.tm_mday, starttime.tm_hour, starttime.tm_min, starttime.tm_sec);
756 757

  dumpfile_id = fopen(dumpfile_name,"w");
758 759 760 761 762

  if (dumpfile_id == NULL) {
    fprintf(stderr, "[EMOS] Error opening dumpfile %s\n",dumpfile_name);
    exit(EXIT_FAILURE);
  }
763 764


jiangx's avatar
jiangx committed
765
  printf("[EMOS] starting dump, channel_buffer_size=%d, fifo %d\n",channel_buffer_size,fifo);
766

767 768 769 770 771 772 773
  while (!oai_exit) {
    /*
    bytes = rtf_read_timed(fifo, fifo2file_ptr, channel_buffer_size,100);
    if (bytes==0)
    continue;
    */
    bytes = rtf_read_all_at_once(fifo, fifo2file_ptr, channel_buffer_size);
774

775 776 777 778
    if (bytes<=0) {
      usleep(100);
      continue;
    }
779

780 781 782
    if (bytes != channel_buffer_size) {
      printf("[EMOS] ERROR! Only got %d bytes instead of %d!\n",bytes,channel_buffer_size);
    }
783

784 785 786 787 788 789
    /*
    if (UE_flag==0)
    printf("eNB: count %d, frame %d, read: %d bytes from the fifo\n",counter, ((fifo_dump_emos_eNB*)fifo2file_ptr)->frame_tx,bytes);
    else
    printf("UE: count %d, frame %d, read: %d bytes from the fifo\n",counter, ((fifo_dump_emos_UE*)fifo2file_ptr)->frame_rx,bytes);
    */
790

791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811
    fifo2file_ptr += channel_buffer_size;
    counter ++;

    if (counter == NO_ESTIMATES_DISK) {
      //reset stuff
      fifo2file_ptr = fifo2file_buffer;
      counter = 0;

      //flush buffer to disk
      if (UE_flag==0)
        printf("[EMOS] eNB: count %d, frame %d, flushing buffer to disk\n",
               counter, ((fifo_dump_emos_eNB*)fifo2file_ptr)->frame_tx);
      else
        printf("[EMOS] UE: count %d, frame %d, flushing buffer to disk\n",
               counter, ((fifo_dump_emos_UE*)fifo2file_ptr)->frame_rx);


      if (fwrite(fifo2file_buffer, sizeof(char), NO_ESTIMATES_DISK*channel_buffer_size, dumpfile_id) != NO_ESTIMATES_DISK*channel_buffer_size) {
        fprintf(stderr, "[EMOS] Error writing to dumpfile\n");
        exit(EXIT_FAILURE);
      }
jiangx's avatar
jiangx committed
812

813 814 815 816
      if (fwrite(&dummy_gps_data, sizeof(char), sizeof(struct gps_fix_t), dumpfile_id) != sizeof(struct gps_fix_t)) {
        printf("[EMOS] Error writing to dumpfile, stopping recording\n");
        exit(EXIT_FAILURE);
      }
817
    }
818 819
  }

820 821 822
  free(fifo2file_buffer);
  fclose(dumpfile_id);
  close(fifo);
823

824 825 826 827 828
  pthread_exit((void*) arg);

}
#endif

829 830


831
#if defined(ENABLE_ITTI)
832 833 834 835 836
static void wait_system_ready (char *message, volatile int *start_flag)
{
  /* Wait for eNB application initialization to be complete (eNB registration to MME) */
  {
    static char *indicator[] = {".    ", "..   ", "...  ", ".... ", ".....",
837 838
                                " ....", "  ...", "   ..", "    .", "     "
                               };
839 840 841 842
    int i = 0;

    while ((!oai_exit) && (*start_flag == 0)) {
      LOG_N(EMU, message, indicator[i]);
843
      fflush(stdout);
844 845 846
      i = (i + 1) % (sizeof(indicator) / sizeof(indicator[0]));
      usleep(200000);
    }
847

848 849 850 851 852
    LOG_D(EMU,"\n");
  }
}
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
853
#if defined(ENABLE_ITTI)
854
void *l2l1_task(void *arg)
855
{
Raymond Knopp's avatar
 
Raymond Knopp committed
856 857 858 859 860
  MessageDef *message_p = NULL;
  int         result;

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
861

Raymond Knopp's avatar
 
Raymond Knopp committed
862 863
  if (UE_flag == 0) {
    /* Wait for the initialize message */
864
    printf("Wait for the ITTI initialize message\n");
865
    do {
Raymond Knopp's avatar
 
Raymond Knopp committed
866
      if (message_p != NULL) {
867 868
        result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
        AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
Raymond Knopp's avatar
 
Raymond Knopp committed
869
      }
870

871 872 873
      itti_receive_msg (TASK_L2L1, &message_p);

      switch (ITTI_MSG_ID(message_p)) {
Raymond Knopp's avatar
 
Raymond Knopp committed
874
      case INITIALIZE_MESSAGE:
875 876 877 878
        /* Start eNB thread */
        LOG_D(EMU, "L2L1 TASK received %s\n", ITTI_MSG_NAME(message_p));
        start_eNB = 1;
        break;
Raymond Knopp's avatar
 
Raymond Knopp committed
879 880

      case TERMINATE_MESSAGE:
881 882 883 884
        printf("received terminate message\n");
        oai_exit=1;
        itti_exit_task ();
        break;
Raymond Knopp's avatar
 
Raymond Knopp committed
885 886

      default:
887 888
        LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
        break;
889
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
890
    } while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE);
891

Raymond Knopp's avatar
 
Raymond Knopp committed
892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912
    result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
  }

  do {
    // Wait for a message
    itti_receive_msg (TASK_L2L1, &message_p);

    switch (ITTI_MSG_ID(message_p)) {
    case TERMINATE_MESSAGE:
      oai_exit=1;
      itti_exit_task ();
      break;

    case ACTIVATE_MESSAGE:
      start_UE = 1;
      break;

    case DEACTIVATE_MESSAGE:
      start_UE = 0;
      break;
913

Raymond Knopp's avatar
 
Raymond Knopp committed
914 915 916 917 918 919 920 921 922 923 924
    case MESSAGE_TEST:
      LOG_I(EMU, "Received %s\n", ITTI_MSG_NAME(message_p));
      break;

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
927
  return NULL;
928 929 930
}
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
931

932 933
void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
934 935 936 937

  unsigned int aa,slot_offset, slot_offset_F;
  int dummy_tx_b[7680*4] __attribute__((aligned(16)));
  int i, tx_offset;
Raymond Knopp's avatar
 
Raymond Knopp committed
938
  int slot_sizeF = (phy_vars_eNB->lte_frame_parms.ofdm_symbol_size)*
939
                   ((phy_vars_eNB->lte_frame_parms.Ncp==1) ? 6 : 7);
940
  int len;
Raymond Knopp's avatar
 
Raymond Knopp committed
941 942

  slot_offset_F = (subframe<<1)*slot_sizeF;
943

Raymond Knopp's avatar
 
Raymond Knopp committed
944 945
  slot_offset = subframe*phy_vars_eNB->lte_frame_parms.samples_per_tti;

Raymond Knopp's avatar
 
Raymond Knopp committed
946 947
  if ((subframe_select(&phy_vars_eNB->lte_frame_parms,subframe)==SF_DL)||
      ((subframe_select(&phy_vars_eNB->lte_frame_parms,subframe)==SF_S))) {
948 949
    //    LOG_D(HW,"Frame %d: Generating slot %d\n",frame,next_slot);

Raymond Knopp's avatar
 
Raymond Knopp committed
950

Raymond Knopp's avatar
 
Raymond Knopp committed
951
    for (aa=0; aa<phy_vars_eNB->lte_frame_parms.nb_antennas_tx; aa++) {
952 953 954
      if (phy_vars_eNB->lte_frame_parms.Ncp == EXTENDED) {
        PHY_ofdm_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F],
                     dummy_tx_b,
955
                     phy_vars_eNB->lte_frame_parms.ofdm_symbol_size,
956 957 958 959 960
                     6,
                     phy_vars_eNB->lte_frame_parms.nb_prefix_samples,
                     CYCLIC_PREFIX);
        PHY_ofdm_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F+slot_sizeF],
                     dummy_tx_b+(phy_vars_eNB->lte_frame_parms.samples_per_tti>>1),
961
                     phy_vars_eNB->lte_frame_parms.ofdm_symbol_size,
962 963 964 965 966 967 968 969
                     6,
                     phy_vars_eNB->lte_frame_parms.nb_prefix_samples,
                     CYCLIC_PREFIX);
      } else {
        normal_prefix_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F],
                          dummy_tx_b,
                          7,
                          &(phy_vars_eNB->lte_frame_parms));
970 971 972 973 974 975
	// if S-subframe generate first slot only
	if (subframe_select(&phy_vars_eNB->lte_frame_parms,subframe) == SF_DL)
	  normal_prefix_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F+slot_sizeF],
			    dummy_tx_b+(phy_vars_eNB->lte_frame_parms.samples_per_tti>>1),
			    7,
			    &(phy_vars_eNB->lte_frame_parms));
Raymond Knopp's avatar
 
Raymond Knopp committed
976
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
977

978 979 980 981 982 983 984
      // if S-subframe generate first slot only
      if (subframe_select(&phy_vars_eNB->lte_frame_parms,subframe) == SF_S)
	len = phy_vars_eNB->lte_frame_parms.samples_per_tti>>1;
      else
	len = phy_vars_eNB->lte_frame_parms.samples_per_tti;
 
     for (i=0; i<len; i++) {
985 986 987 988 989 990 991 992
        tx_offset = (int)slot_offset+time_offset[aa]+i;

        if (tx_offset<0)
          tx_offset += LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti;

        if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti))
          tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti;

993 994 995
	((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[0] = ((short*)dummy_tx_b)[2*i]<<openair0_cfg[0].iq_txshift;
	
	((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[1] = ((short*)dummy_tx_b)[2*i+1]<<openair0_cfg[0].iq_txshift;
996

997 998
	printf("dddddddddddddddddddddd%d\n\n\n\n",openair0_cfg[0].iq_txshift);
  
999 1000 1001 1002 1003 1004 1005
     }
     // if S-subframe switch to RX in second subframe
     if (subframe_select(&phy_vars_eNB->lte_frame_parms,subframe) == SF_S) {
       for (i=0; i<len; i++) {
	 phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset++] = 0x00010001;
       }
     }
1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024

     if ((((phy_vars_eNB->lte_frame_parms.tdd_config==0) ||
	  (phy_vars_eNB->lte_frame_parms.tdd_config==1) ||
	  (phy_vars_eNB->lte_frame_parms.tdd_config==2) ||
	  (phy_vars_eNB->lte_frame_parms.tdd_config==6)) && 
	  (subframe==0)) || (subframe==5)) {
       // turn on tx switch N_TA_offset before
       //LOG_D(HW,"subframe %d, time to switch to tx (N_TA_offset %d, slot_offset %d) \n",subframe,phy_vars_eNB->N_TA_offset,slot_offset);
       for (i=0; i<phy_vars_eNB->N_TA_offset; i++) {
	 tx_offset = (int)slot_offset+time_offset[aa]+i-phy_vars_eNB->N_TA_offset/2;
	 if (tx_offset<0)
	   tx_offset += LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti;
	 
	 if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti))
	   tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti;
	 
	 phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset] = 0x00000000;
       }
     }
Raymond Knopp's avatar
 
Raymond Knopp committed
1025 1026 1027 1028
    }
  }
}

1029 1030 1031 1032 1033 1034 1035 1036 1037
/* mutex, cond and variable to serialize phy proc TX calls
 * (this mechanism may be relaxed in the future for better
 * performances)
 */
static struct {
  pthread_mutex_t  mutex_phy_proc_tx;
  pthread_cond_t   cond_phy_proc_tx;
  volatile uint8_t phy_proc_CC_id;
} sync_phy_proc[NUM_ENB_THREADS];
Raymond Knopp's avatar
 
Raymond Knopp committed
1038

1039 1040 1041 1042 1043 1044 1045 1046 1047
/*!
 * \brief The transmit thread of eNB.
 * \ref NUM_ENB_THREADS threads of this type are active at the same time.
 * \param param is a \ref eNB_proc_t structure which contains the info what to process.
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
static void* eNB_thread_tx( void* param )
{
  static int eNB_thread_tx_status[NUM_ENB_THREADS];
Raymond Knopp's avatar
 
Raymond Knopp committed
1048 1049

  eNB_proc_t *proc = (eNB_proc_t*)param;
1050 1051
  FILE  *tx_time_file;
  char tx_time_name[101];
kaltenbe's avatar
kaltenbe committed
1052

1053 1054 1055 1056
  if (opp_enabled == 1) {
    snprintf(tx_time_name, 100,"/tmp/%s_tx_time_thread_sf_%d", "eNB", proc->subframe);
    tx_time_file = fopen(tx_time_name,"w");
  }
1057 1058 1059
  // set default return value
  eNB_thread_tx_status[proc->subframe] = 0;

1060 1061
  MSC_START_USE();

Raymond Knopp's avatar
 
Raymond Knopp committed
1062 1063
#ifdef RTAI
  RT_TASK *task;
1064
  char task_name[8];
Raymond Knopp's avatar
 
Raymond Knopp committed
1065

1066
  sprintf(task_name,"TXC%dS%d",proc->CC_id,proc->subframe);
Raymond Knopp's avatar
 
Raymond Knopp committed
1067 1068
  task = rt_task_init_schmod(nam2num(task_name), 0, 0, 0, SCHED_FIFO, 0xF);

1069 1070 1071
  if (task == NULL) {
    LOG_E(PHY,"[SCHED][eNB] Problem starting eNB_proc_TX thread_index %d (%s)!!!!\n",proc->subframe,task_name);
    return 0;
1072 1073 1074 1075 1076
  } else {
    LOG_I(PHY,"[SCHED][eNB] eNB TX thread CC %d SF %d started with id %p\n",
          proc->CC_id,
          proc->subframe,
          task);
1077
  }
1078

Raymond Knopp's avatar
 
Raymond Knopp committed
1079
#else
1080
#ifdef LOWLATENCY
1081 1082
  struct sched_attr attr;
  unsigned int flags = 0;
navid's avatar
navid committed
1083 1084 1085 1086 1087 1088 1089
  uint64_t runtime  = (uint64_t) (get_runtime_tx(proc->subframe, runtime_phy_tx, target_dl_mcs,frame_parms[0]->N_RB_DL,cpuf,PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx) *  1000000); 
  uint64_t deadline = 1   *  1000000; // each tx thread will finish within 1ms
  uint64_t period   = 1   * 10000000; // each tx thread has a period of 10ms from the starting point
  if (runtime > 1000000 ){
    LOG_W(HW,"estimated runtime %d is larger than 1ms, adjusting\n",runtime);
    runtime = (0.97 * 100) * 10000; 
  }
1090

1091 1092 1093 1094
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1095

navid's avatar
navid committed
1096 1097 1098 1099
  attr.sched_policy   = SCHED_DEADLINE;
  attr.sched_runtime  = runtime;
  attr.sched_deadline = deadline;
  attr.sched_period   = period; 
1100

1101 1102 1103 1104
  if (sched_setattr(0, &attr, flags) < 0 ) {
    perror("[SCHED] eNB tx thread: sched_setattr failed\n");
    return &eNB_thread_tx_status[proc->subframe];
  }
1105

navid's avatar
navid committed
1106
  LOG_I( HW, "[SCHED] eNB TX deadline thread %d(TID %ld) started on CPU %d\n", proc->subframe, gettid(), sched_getcpu() );
1107
#else
1108
  LOG_I( HW, "[SCHED][eNB] TX thread %d started on CPU %d TID %d\n", proc->subframe, sched_getcpu(),gettid() );
1109 1110
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
1111 1112 1113 1114 1115 1116 1117 1118
#endif

  mlockall(MCL_CURRENT | MCL_FUTURE);

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

1119
  while (!oai_exit) {
1120

1121
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe), 0 );
1122

1123
    if (pthread_mutex_lock(&proc->mutex_tx) != 0) {
1124
      LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc %d\n", proc->subframe );
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1125
      exit_fun("nothing to add");
1126
      break;
1127
    }
1128

1129
    while (proc->instance_cnt_tx < 0) {
1130 1131 1132
      // most of the time the thread is waiting here
      // proc->instance_cnt_tx is -1
      pthread_cond_wait( &proc->cond_tx, &proc->mutex_tx ); // this unlocks mutex_tx while waiting and then locks it again
1133
    }
1134

1135 1136 1137 1138 1139
    if (pthread_mutex_unlock(&proc->mutex_tx) != 0) {
      LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for eNB TX proc %d\n",proc->subframe);
      exit_fun("nothing to add");
      break;
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1140

1141 1142
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe), 1 );
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX_ENB, proc->frame_tx );
1143 1144 1145
    start_meas( &softmodem_stats_tx_sf[proc->subframe] );

    if (oai_exit) break;
1146

1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158
    if (((PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == TDD) &&
         ((subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_tx) == SF_DL) ||
          (subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_tx) == SF_S))) ||
        (PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == FDD)) {
      /* run PHY TX procedures the one after the other for all CCs to avoid race conditions
       * (may be relaxed in the future for performance reasons)
       */
      if (pthread_mutex_lock(&sync_phy_proc[proc->subframe].mutex_phy_proc_tx) != 0) {
        LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX proc %d\n", proc->subframe);
        exit_fun("nothing to add");
        break;
      }
1159 1160
      /* wait for our turn or oai_exit */
      while (sync_phy_proc[proc->subframe].phy_proc_CC_id != proc->CC_id && !oai_exit) {
1161 1162 1163
        pthread_cond_wait(&sync_phy_proc[proc->subframe].cond_phy_proc_tx,
                          &sync_phy_proc[proc->subframe].mutex_phy_proc_tx);
      }
ghaddab's avatar
ghaddab committed
1164

1165 1166 1167
      if (pthread_mutex_unlock(&sync_phy_proc[proc->subframe].mutex_phy_proc_tx) != 0) {
        LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc %d\n", proc->subframe);
        exit_fun("nothing to add");
1168 1169
      }

1170 1171 1172
      if (oai_exit)
        break;

1173
      phy_procedures_eNB_TX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay, NULL );
1174

1175
      /* we're done, let the next one proceed */
1176 1177 1178 1179 1180
      if (pthread_mutex_lock(&sync_phy_proc[proc->subframe].mutex_phy_proc_tx) != 0) {
        LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX proc %d\n", proc->subframe);
        exit_fun("nothing to add");
        break;
      }
1181 1182 1183 1184
      sync_phy_proc[proc->subframe].phy_proc_CC_id++;
      sync_phy_proc[proc->subframe].phy_proc_CC_id %= MAX_NUM_CCs;
      pthread_cond_broadcast(&sync_phy_proc[proc->subframe].cond_phy_proc_tx);
      if (pthread_mutex_unlock(&sync_phy_proc[proc->subframe].mutex_phy_proc_tx) != 0) {
1185
        LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc %d\n", proc->subframe);
1186 1187 1188
        exit_fun("nothing to add");
        break;
      }
1189
    }
1190

1191
    do_OFDM_mod_rt( proc->subframe_tx, PHY_vars_eNB_g[0][proc->CC_id] );
kaltenbe's avatar
kaltenbe committed
1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205
    /*
    short *txdata = (short*)&PHY_vars_eNB_g[0][proc->CC_id]->lte_eNB_common_vars.txdata[0][0][proc->subframe_tx*PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.samples_per_tti];
    int i;
    for (i=0;i<7680*2;i+=8) {
      txdata[i] = 2047;
      txdata[i+1] = 0;
      txdata[i+2] = 0;
      txdata[i+3] = 2047;
      txdata[i+4] = -2047;
      txdata[i+5] = 0;
      txdata[i+6] = 0;
      txdata[i+7] = -2047;
    }
    */
1206 1207 1208 1209 1210
    if (pthread_mutex_lock(&proc->mutex_tx) != 0) {
      LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc %d\n", proc->subframe );
      exit_fun("nothing to add");
      break;
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1211

1212 1213 1214 1215 1216 1217 1218 1219 1220
    proc->instance_cnt_tx--;

    if (pthread_mutex_unlock(&proc->mutex_tx) != 0) {
      LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB TX proc %d\n", proc->subframe );
      exit_fun("nothing to add");
      break;
    }

    proc->frame_tx++;
1221

1222 1223
    if (proc->frame_tx==1024)
      proc->frame_tx=0;
1224
    stop_meas( &softmodem_stats_tx_sf[proc->subframe] );
1225 1226 1227 1228 1229 1230 1231
#ifdef LOWLATENCY
    if (opp_enabled){
      if(softmodem_stats_tx_sf[proc->subframe].diff_now/(cpuf) > attr.sched_runtime){
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_TX_ENB, (softmodem_stats_tx_sf[proc->subframe].diff_now/cpuf - attr.sched_runtime)/1000000.0);
      }
    }
#endif 
1232 1233
    print_meas_now(&softmodem_stats_tx_sf[proc->subframe],"eNB_TX_SF",proc->subframe, tx_time_file);

1234 1235
  }

1236 1237


1238
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe), 0 );
Raymond Knopp's avatar
 
Raymond Knopp committed
1239

Raymond Knopp's avatar
 
Raymond Knopp committed
1240 1241 1242
#ifdef HARD_RT
  rt_make_soft_real_time();
#endif
1243

Raymond Knopp's avatar
 
Raymond Knopp committed
1244
#ifdef DEBUG_THREADS
1245
  printf( "Exiting eNB thread TX %d\n", proc->subframe );
Raymond Knopp's avatar
 
Raymond Knopp committed
1246 1247 1248 1249 1250
#endif
  // clean task
#ifdef RTAI
  rt_task_delete(task);
#endif
1251

1252 1253
  eNB_thread_tx_status[proc->subframe] = 0;
  return &eNB_thread_tx_status[proc->subframe];
Raymond Knopp's avatar
 
Raymond Knopp committed
1254 1255 1256
}


1257 1258 1259 1260 1261 1262 1263 1264 1265 1266
/*!
 * \brief The receive thread of eNB.
 * \ref NUM_ENB_THREADS threads of this type are active at the same time.
 * \param param is a \ref eNB_proc_t structure which contains the info what to process.
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
static void* eNB_thread_rx( void* param )
{
  static int eNB_thread_rx_status[NUM_ENB_THREADS];

Raymond Knopp's avatar
 
Raymond Knopp committed
1267
  eNB_proc_t *proc = (eNB_proc_t*)param;
1268

1269 1270
  FILE  *rx_time_file;
  char rx_time_name[101];
Raymond Knopp's avatar
 
Raymond Knopp committed
1271 1272
  int i;

1273 1274 1275 1276
  if (opp_enabled == 1){
    snprintf(rx_time_name, 100,"/tmp/%s_rx_time_thread_sf_%d", "eNB", proc->subframe);
    rx_time_file = fopen(rx_time_name,"w");
  }
1277 1278 1279
  // set default return value
  eNB_thread_rx_status[proc->subframe] = 0;

1280 1281
  MSC_START_USE();

Raymond Knopp's avatar
 
Raymond Knopp committed
1282 1283
#ifdef RTAI
  RT_TASK *task;
1284
  char task_name[8];
Raymond Knopp's avatar
 
Raymond Knopp committed
1285

1286
  sprintf(task_name,"RXC%1dS%1d",proc->CC_id,proc->subframe);
Raymond Knopp's avatar
 
Raymond Knopp committed
1287 1288 1289
  task = rt_task_init_schmod(nam2num(task_name), 0, 0, 0, SCHED_FIFO, 0xF);

  if (task==NULL) {
1290 1291
    LOG_E(PHY,"[SCHED][eNB] Problem starting eNB_proc_RX thread_index %d (%s)!!!!\n",proc->subframe,task_name);
    return 0;
1292
  } else {
1293
    LOG_I(PHY,"[SCHED][eNB] eNB RX thread CC_id %d SF %d started with id %p\n", /*  on CPU %d*/
1294 1295 1296
          proc->CC_id,
          proc->subframe,
          task); /*,rtai_cpuid()*/
Raymond Knopp's avatar
 
Raymond Knopp committed
1297
  }
1298

Raymond Knopp's avatar
 
Raymond Knopp committed
1299
#else
1300
#ifdef LOWLATENCY
1301 1302
  struct sched_attr attr;
  unsigned int flags = 0;
navid's avatar
navid committed
1303 1304 1305 1306 1307 1308 1309 1310
  uint64_t runtime  = get_runtime_rx(proc->subframe, runtime_phy_rx, target_ul_mcs,frame_parms[0]->N_RB_DL,cpuf,PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx)  *  1000000; 
  uint64_t deadline = 1   *  1000000;
  uint64_t period   = 1   * 10000000; // each rx thread has a period of 10ms from the starting point
  if (runtime  > 2300000 ) {
    LOG_W(HW,"estimated rx runtime %d is larger than expected, adjusting\n",runtime);
    runtime   = 2300000;
    deadline  = runtime + 100000;
  }
1311

1312 1313 1314 1315
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1316

1317
  attr.sched_policy = SCHED_DEADLINE;
navid's avatar
navid committed
1318 1319 1320
  attr.sched_runtime  = runtime;
  attr.sched_deadline = deadline;
  attr.sched_period   = period; 
1321 1322

  if (sched_setattr(0, &attr, flags) < 0 ) {
1323
    perror("[SCHED] eNB RX sched_setattr failed\n");
1324
    return &eNB_thread_rx_status[proc->subframe];
1325
  }
1326

1327
  LOG_I( HW, "[SCHED] eNB RX deadline thread %d(TID %ld) started on CPU %d\n", proc->subframe, gettid(), sched_getcpu() );
1328
#else
1329
  LOG_I( HW, "[SCHED][eNB] RX thread %d started on CPU %d TID %d\n", proc->subframe, sched_getcpu(),gettid() );
Raymond Knopp's avatar
 
Raymond Knopp committed
1330
#endif
1331
#endif // RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
1332 1333 1334 1335 1336 1337 1338

  mlockall(MCL_CURRENT | MCL_FUTURE);

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

1339
  while (!oai_exit) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1340

1341
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 0 );
1342

Raymond Knopp's avatar
 
Raymond Knopp committed
1343
    if (pthread_mutex_lock(&proc->mutex_rx) != 0) {
1344 1345 1346
      LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB RX proc %d\n", proc->subframe );
      exit_fun( "error locking mutex" );
      break;
Raymond Knopp's avatar
 
Raymond Knopp committed
1347 1348
    }

1349
    while (proc->instance_cnt_rx < 0) {
1350 1351 1352
      // most of the time the thread is waiting here
      // proc->instance_cnt_rx is -1
      pthread_cond_wait( &proc->cond_rx, &proc->mutex_rx ); // this unlocks mutex_rx while waiting and then locks it again
Raymond Knopp's avatar
 
Raymond Knopp committed
1353
    }
1354 1355 1356 1357 1358 1359 1360

    if (pthread_mutex_unlock(&proc->mutex_rx) != 0) {
      LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB RX proc %d\n", proc->subframe );
      exit_fun( "error unlocking mutex" );
      break;
    }

1361 1362
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 1 );
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx );
1363
    start_meas( &softmodem_stats_rx_sf[proc->subframe] );
1364

Raymond Knopp's avatar
 
Raymond Knopp committed
1365
    if (oai_exit) break;
1366

Raymond Knopp's avatar
 
Raymond Knopp committed
1367
    if ((((PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == TDD )&&(subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_rx)==SF_UL)) ||
1368
         (PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == FDD))) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1369

1370
      phy_procedures_eNB_RX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay );
Raymond Knopp's avatar
 
Raymond Knopp committed
1371
    }
1372 1373

    if ((subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_rx) == SF_S)) {
1374
      phy_procedures_eNB_S_RX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay );
Raymond Knopp's avatar
 
Raymond Knopp committed
1375
    }
1376

Raymond Knopp's avatar
 
Raymond Knopp committed
1377
    if (pthread_mutex_lock(&proc->mutex_rx) != 0) {
1378 1379 1380
      LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB RX proc %d\n", proc->subframe );
      exit_fun( "error locking mutex" );
      break;
Raymond Knopp's avatar
 
Raymond Knopp committed
1381
    }
1382 1383 1384 1385 1386 1387 1388

    proc->instance_cnt_rx--;

    if (pthread_mutex_unlock(&proc->mutex_rx) != 0) {
      LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB RX proc %d\n", proc->subframe );
      exit_fun( "error unlocking mutex" );
      break;
Raymond Knopp's avatar
 
Raymond Knopp committed
1389
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1390 1391

    proc->frame_rx++;
1392

Raymond Knopp's avatar
 
Raymond Knopp committed
1393 1394
    if (proc->frame_rx==1024)
      proc->frame_rx=0;
1395

1396
    stop_meas( &softmodem_stats_rx_sf[proc->subframe] );
1397 1398 1399 1400 1401 1402 1403
#ifdef LOWLATENCY
    if (opp_enabled){
      if(softmodem_stats_rx_sf[proc->subframe].diff_now/(cpuf) > attr.sched_runtime){
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_RX_ENB, (softmodem_stats_rx_sf[proc->subframe].diff_now/cpuf - attr.sched_runtime)/1000000.0);
      }
    }
#endif  
1404
    print_meas_now(&softmodem_stats_rx_sf[proc->subframe],"eNB_RX_SF",proc->subframe, rx_time_file);
Raymond Knopp's avatar
 
Raymond Knopp committed
1405
  }
1406

1407
  //stop_meas( &softmodem_stats_rx_sf[proc->subframe] );
1408
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 0 );
1409

Raymond Knopp's avatar
 
Raymond Knopp committed
1410
#ifdef HARD_RT
Raymond Knopp's avatar
 
Raymond Knopp committed
1411 1412 1413 1414
  rt_make_soft_real_time();
#endif

#ifdef DEBUG_THREADS
1415
  printf( "Exiting eNB thread RX %d\n", proc->subframe );
Raymond Knopp's avatar
 
Raymond Knopp committed
1416 1417 1418 1419
#endif
  // clean task
#ifdef RTAI
  rt_task_delete(task);
Raymond Knopp's avatar
 
Raymond Knopp committed
1420 1421
#endif

1422 1423
  eNB_thread_rx_status[proc->subframe] = 0;
  return &eNB_thread_rx_status[proc->subframe];
Raymond Knopp's avatar
 
Raymond Knopp committed
1424 1425 1426 1427
}



Raymond Knopp's avatar
 
Raymond Knopp committed
1428

1429 1430
void init_eNB_proc(void)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1431
  int i;
Raymond Knopp's avatar
 
Raymond Knopp committed
1432 1433
  int CC_id;

1434 1435 1436
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    for (i=0; i<NUM_ENB_THREADS; i++) {
      // set the stack size
navid's avatar
navid committed
1437
     
1438

navid's avatar
navid committed
1439 1440 1441 1442 1443 1444
#ifndef LOWLATENCY 
      /*  
       pthread_attr_init( &attr_eNB_proc_tx[CC_id][i] );
       if (pthread_attr_setstacksize( &attr_eNB_proc_tx[CC_id][i], 64 *PTHREAD_STACK_MIN ) != 0)
        perror("[ENB_PROC_TX] setting thread stack size failed\n");
      
1445
      pthread_attr_init( &attr_eNB_proc_rx[CC_id][i] );
navid's avatar
navid committed
1446
      if (pthread_attr_setstacksize( &attr_eNB_proc_rx[CC_id][i], 64 * PTHREAD_STACK_MIN ) != 0)
1447
        perror("[ENB_PROC_RX] setting thread stack size failed\n");
1448
      */
1449
      // set the kernel scheduling policy and priority
Raymond Knopp's avatar
 
Raymond Knopp committed
1450 1451 1452 1453 1454 1455
      sched_param_eNB_proc_tx[CC_id][i].sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY;
      pthread_attr_setschedparam  (&attr_eNB_proc_tx[CC_id][i], &sched_param_eNB_proc_tx[CC_id][i]);
      pthread_attr_setschedpolicy (&attr_eNB_proc_tx[CC_id][i], SCHED_FIFO);
      sched_param_eNB_proc_rx[CC_id][i].sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY;
      pthread_attr_setschedparam  (&attr_eNB_proc_rx[CC_id][i], &sched_param_eNB_proc_rx[CC_id][i]);
      pthread_attr_setschedpolicy (&attr_eNB_proc_rx[CC_id][i], SCHED_FIFO);
1456
      printf("Setting OS scheduler to SCHED_FIFO for eNB [cc%d][thread%d] \n",CC_id, i);
1457
#endif
1458 1459 1460
      PHY_vars_eNB_g[0][CC_id]->proc[i].instance_cnt_tx = -1;
      PHY_vars_eNB_g[0][CC_id]->proc[i].instance_cnt_rx = -1;
      PHY_vars_eNB_g[0][CC_id]->proc[i].subframe = i;
Raymond Knopp's avatar
 
Raymond Knopp committed
1461
      PHY_vars_eNB_g[0][CC_id]->proc[i].CC_id = CC_id;
1462 1463 1464 1465
      pthread_mutex_init( &PHY_vars_eNB_g[0][CC_id]->proc[i].mutex_tx, NULL);
      pthread_mutex_init( &PHY_vars_eNB_g[0][CC_id]->proc[i].mutex_rx, NULL);
      pthread_cond_init( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_tx, NULL);
      pthread_cond_init( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_rx, NULL);
1466 1467 1468 1469
#ifndef LOWLATENCY
      pthread_create( &PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_tx, &attr_eNB_proc_tx[CC_id][i], eNB_thread_tx, &PHY_vars_eNB_g[0][CC_id]->proc[i] );
      pthread_create( &PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_rx, &attr_eNB_proc_rx[CC_id][i], eNB_thread_rx, &PHY_vars_eNB_g[0][CC_id]->proc[i] );
#else 
1470 1471
      pthread_create( &PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_tx, NULL, eNB_thread_tx, &PHY_vars_eNB_g[0][CC_id]->proc[i] );
      pthread_create( &PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_rx, NULL, eNB_thread_rx, &PHY_vars_eNB_g[0][CC_id]->proc[i] );
1472
#endif
1473 1474 1475 1476 1477
      char name[16];
      snprintf( name, sizeof(name), "TX %d", i );
      pthread_setname_np( PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_tx, name );
      snprintf( name, sizeof(name), "RX %d", i );
      pthread_setname_np( PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_rx, name );
Raymond Knopp's avatar
 
Raymond Knopp committed
1478 1479
      PHY_vars_eNB_g[0][CC_id]->proc[i].frame_tx = 0;
      PHY_vars_eNB_g[0][CC_id]->proc[i].frame_rx = 0;
1480
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
1481 1482
      PHY_vars_eNB_g[0][CC_id]->proc[i].subframe_rx = (i+9)%10;
      PHY_vars_eNB_g[0][CC_id]->proc[i].subframe_tx = (i+1)%10;
Raymond Knopp's avatar
 
Raymond Knopp committed
1483
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
1484 1485
      PHY_vars_eNB_g[0][CC_id]->proc[i].subframe_rx = i;
      PHY_vars_eNB_g[0][CC_id]->proc[i].subframe_tx = (i+2)%10;
Raymond Knopp's avatar
 
Raymond Knopp committed
1486
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1487
    }
1488 1489


1490
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
1491 1492
    // TX processes subframe + 1, RX subframe -1
    // Note this inialization is because the first process awoken for frame 0 is number 1 and so processes 9 and 0 have to start with frame 1
1493

Raymond Knopp's avatar
 
Raymond Knopp committed
1494
    //PHY_vars_eNB_g[0][CC_id]->proc[0].frame_rx = 1023;
Raymond Knopp's avatar
 
Raymond Knopp committed
1495 1496
    PHY_vars_eNB_g[0][CC_id]->proc[9].frame_tx = 1;
    PHY_vars_eNB_g[0][CC_id]->proc[0].frame_tx = 1;
Raymond Knopp's avatar
 
Raymond Knopp committed
1497
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
1498 1499
    // TX processes subframe +2, RX subframe
    // Note this inialization is because the first process awoken for frame 0 is number 1 and so processes 8,9 and 0 have to start with frame 1
Raymond Knopp's avatar
 
Raymond Knopp committed
1500
    //    PHY_vars_eNB_g[0][CC_id]->proc[7].frame_tx = 1;
Raymond Knopp's avatar
 
Raymond Knopp committed
1501 1502
    PHY_vars_eNB_g[0][CC_id]->proc[8].frame_tx = 1;
    PHY_vars_eNB_g[0][CC_id]->proc[9].frame_tx = 1;
Raymond Knopp's avatar
 
Raymond Knopp committed
1503
    //    PHY_vars_eNB_g[0][CC_id]->proc[0].frame_tx = 1;
Raymond Knopp's avatar
 
Raymond Knopp committed
1504
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1505
  }
1506 1507 1508 1509 1510 1511 1512

  /* setup PHY proc TX sync mechanism */
  for (i=0; i<NUM_ENB_THREADS; i++) {
    pthread_mutex_init(&sync_phy_proc[i].mutex_phy_proc_tx, NULL);
    pthread_cond_init(&sync_phy_proc[i].cond_phy_proc_tx, NULL);
    sync_phy_proc[i].phy_proc_CC_id = 0;
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
1513
}
Raymond Knopp's avatar
 
Raymond Knopp committed
1514

1515 1516 1517 1518 1519 1520
/*!
 * \brief Terminate eNB TX and RX threads.
 */
void kill_eNB_proc(void)
{
  int *status;
Raymond Knopp's avatar
 
Raymond Knopp committed
1521

1522 1523
  for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++)
    for (int i=0; i<NUM_ENB_THREADS; i++) {
1524

Raymond Knopp's avatar
 
Raymond Knopp committed
1525
#ifdef DEBUG_THREADS
1526
      printf( "Killing TX CC_id %d thread %d\n", CC_id, i );
Raymond Knopp's avatar
 
Raymond Knopp committed
1527
#endif
1528 1529 1530

      PHY_vars_eNB_g[0][CC_id]->proc[i].instance_cnt_tx = 0; // FIXME data race!
      pthread_cond_signal( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_tx );
1531
      pthread_cond_broadcast(&sync_phy_proc[i].cond_phy_proc_tx);
1532

Raymond Knopp's avatar
 
Raymond Knopp committed
1533
#ifdef DEBUG_THREADS
1534
      printf( "Joining eNB TX CC_id %d thread %d...\n", CC_id, i );
Raymond Knopp's avatar
 
Raymond Knopp committed
1535
#endif
1536
      int result = pthread_join( PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_tx, (void**)&status );
1537

Raymond Knopp's avatar
 
Raymond Knopp committed
1538
#ifdef DEBUG_THREADS
1539

1540 1541 1542 1543 1544 1545 1546 1547 1548
      if (result != 0) {
        printf( "Error joining thread.\n" );
      } else {
        if (status) {
          printf( "status %d\n", *status );
        } else {
          printf( "The thread was killed. No status available.\n" );
        }
      }
1549

1550 1551
#else
      UNUSED(result)
Raymond Knopp's avatar
 
Raymond Knopp committed
1552
#endif
1553

Raymond Knopp's avatar
 
Raymond Knopp committed
1554
#ifdef DEBUG_THREADS
1555
      printf( "Killing RX CC_id %d thread %d\n", CC_id, i );
Raymond Knopp's avatar
 
Raymond Knopp committed
1556
#endif
1557 1558 1559 1560

      PHY_vars_eNB_g[0][CC_id]->proc[i].instance_cnt_rx = 0; // FIXME data race!
      pthread_cond_signal( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_rx );

Raymond Knopp's avatar
 
Raymond Knopp committed
1561
#ifdef DEBUG_THREADS
1562
      printf( "Joining eNB RX CC_id %d thread %d...\n", CC_id, i );
Raymond Knopp's avatar
 
Raymond Knopp committed
1563
#endif
1564 1565
      result = pthread_join( PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_rx, (void**)&status );

1566 1567
#ifdef DEBUG_THREADS

1568 1569 1570 1571 1572 1573 1574 1575 1576
      if (result != 0) {
        printf( "Error joining thread.\n" );
      } else {
        if (status) {
          printf( "status %d\n", *status );
        } else {
          printf( "The thread was killed. No status available.\n" );
        }
      }
1577

1578 1579
#else
      UNUSED(result)
Raymond Knopp's avatar
 
Raymond Knopp committed
1580
#endif
1581 1582 1583 1584 1585

      pthread_mutex_destroy( &PHY_vars_eNB_g[0][CC_id]->proc[i].mutex_tx );
      pthread_mutex_destroy( &PHY_vars_eNB_g[0][CC_id]->proc[i].mutex_rx );
      pthread_cond_destroy( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_tx );
      pthread_cond_destroy( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_rx );
Raymond Knopp's avatar
 
Raymond Knopp committed
1586
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1587 1588 1589
}


Raymond Knopp's avatar
 
Raymond Knopp committed
1590 1591


1592

Raymond Knopp's avatar
 
Raymond Knopp committed
1593

1594 1595 1596 1597 1598 1599
/*!
 * \brief This is the main eNB thread.
 * \param arg unused
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
static void* eNB_thread( void* arg )
1600
{
1601 1602
  UNUSED(arg);
  static int eNB_thread_status;
1603

1604
  unsigned char slot;
1605
#ifdef EXMIMO
1606
  slot=0;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1607
  RTIME time_in;
Raymond Knopp's avatar
 
Raymond Knopp committed
1608
  volatile unsigned int *DAQ_MBOX = openair0_daq_cnt();
Raymond Knopp's avatar
 
Raymond Knopp committed
1609 1610
  int mbox_target=0,mbox_current=0;
  int hw_slot,delay_cnt;
Raymond Knopp's avatar
 
Raymond Knopp committed
1611 1612
  int diff;
  int ret;
1613
  int first_run=1;
Raymond Knopp's avatar
 
Raymond Knopp committed
1614
#else
1615 1616 1617
  // the USRP implementation operates on subframes, not slots
  // one subframe consists of one even and one odd slot
  slot = 1;
1618
  int spp;
1619
  int tx_launched = 0;
1620
  int card=0;
1621 1622 1623

  void *rxp[2]; // FIXME hard coded array size; indexed by lte_frame_parms.nb_antennas_rx
  void *txp[2]; // FIXME hard coded array size; indexed by lte_frame_parms.nb_antennas_tx
Raymond Knopp's avatar
 
Raymond Knopp committed
1624

1625
  int hw_subframe = 0; // 0..NUM_ENB_THREADS-1 => 0..9
1626
  
1627
  unsigned int rx_pos = 0;
1628
  unsigned int tx_pos = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
1629
#endif
1630
  int CC_id=0;	
1631
  struct timespec trx_time0, trx_time1, trx_time2;
1632

1633
#ifdef RTAI
1634
  RT_TASK* task = rt_task_init_schmod(nam2num("eNBmain"), 0, 0, 0, SCHED_FIFO, 0xF);
1635
#else
1636
#ifdef LOWLATENCY
1637 1638 1639
  struct sched_attr attr;
  unsigned int flags = 0;

Raymond Knopp's avatar
 
Raymond Knopp committed
1640 1641 1642 1643
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1644

1645
  /* This creates a .2 ms  reservation */
Raymond Knopp's avatar
 
Raymond Knopp committed
1646
  attr.sched_policy = SCHED_DEADLINE;
navid's avatar
navid committed
1647
  attr.sched_runtime  = (0.3 * 100) * 10000;
1648 1649
  attr.sched_deadline = (0.9 * 100) * 10000;
  attr.sched_period   = 1 * 1000000;
1650

Lionel Gauthier's avatar
Lionel Gauthier committed
1651

Raymond Knopp's avatar
 
Raymond Knopp committed
1652 1653 1654 1655
  /* pin the eNB main thread to CPU0*/
  /* if (pthread_setaffinity_np(pthread_self(), sizeof(mask),&mask) <0) {
     perror("[MAIN_ENB_THREAD] pthread_setaffinity_np failed\n");
     }*/
1656

1657
  if (sched_setattr(0, &attr, flags) < 0 ) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1658 1659 1660 1661
    perror("[SCHED] main eNB thread: sched_setattr failed\n");
    exit_fun("Nothing to add");
  } else {
    LOG_I(HW,"[SCHED][eNB] eNB main deadline thread %ld started on CPU %d\n",
1662
          gettid(),sched_getcpu());
Raymond Knopp's avatar
 
Raymond Knopp committed
1663
  }
1664

1665
#endif
1666 1667
#endif

1668 1669 1670 1671 1672
  // stop early, if an exit is requested
  // FIXME really neccessary?
  if (oai_exit)
    goto eNB_thread_cleanup;

1673
#ifdef RTAI
1674
  printf( "[SCHED][eNB] Started eNB main thread (id %p)\n", task );
Raymond Knopp's avatar
 
Raymond Knopp committed
1675
#else
1676
  printf( "[SCHED][eNB] Started eNB main thread on CPU %d TID %d\n", sched_getcpu(), gettid());
1677 1678 1679
#endif

#ifdef HARD_RT
1680
  rt_make_hard_real_time();
1681 1682
#endif

1683 1684 1685 1686 1687 1688 1689 1690
  printf("eNB_thread: mlockall in ...\n");
  mlockall(MCL_CURRENT | MCL_FUTURE);
  printf("eNB_thread: mlockall out ...\n");

  timing_info.time_min = 100000000ULL;
  timing_info.time_max = 0;
  timing_info.time_avg = 0;
  timing_info.n_samples = 0;
1691

1692 1693
  printf( "waiting for sync (eNB_thread)\n" );
  pthread_mutex_lock( &sync_mutex );
1694

1695 1696
  while (sync_var<0)
    pthread_cond_wait( &sync_cond, &sync_mutex );
1697

1698
  pthread_mutex_unlock(&sync_mutex);
1699

1700 1701
  printf( "got sync (eNB_thread)\n" );

1702
  int frame = 0;
1703

1704
#ifndef EXMIMO
1705 1706
  spp        = openair0_cfg[0].samples_per_packet;
  tx_pos     = openair0_cfg[0].tx_scheduling_advance;
1707
#endif
1708

1709 1710 1711 1712
#if defined(ENABLE_ITTI)
  wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB);
#endif 

1713 1714
  while (!oai_exit) {
    start_meas( &softmodem_stats_mt );
Raymond Knopp's avatar
 
Raymond Knopp committed
1715

1716
#ifdef EXMIMO
1717 1718
    hw_slot = (((((volatile unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15;
    //        LOG_D(HW,"eNB frame %d, time %llu: slot %d, hw_slot %d (mbox %d)\n",frame,rt_get_time_ns(),slot,hw_slot,((unsigned int *)DAQ_MBOX)[0]);
1719 1720
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME, hw_slot>>1);
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME, frame);
1721 1722 1723 1724
    //this is the mbox counter where we should be
    mbox_target = mbox_bounds[slot];
    //this is the mbox counter where we are
    mbox_current = ((volatile unsigned int *)DAQ_MBOX)[0];
1725

1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736
    //this is the time we need to sleep in order to synchronize with the hw (in multiples of DAQ_PERIOD)
    if ((mbox_current>=135) && (mbox_target<15)) //handle the frame wrap-arround
      diff = 150-mbox_current+mbox_target;
    else if ((mbox_current<15) && (mbox_target>=135))
      diff = -150+mbox_target-mbox_current;
    else
      diff = mbox_target - mbox_current;

    //when we start the aquisition we want to start with slot 0, so we rather wait for the hardware than to advance the slot number (a positive diff will cause the programm to go into the second if clause rather than the first)
    if (first_run==1) {
      first_run=0;
1737

1738
      if (diff<0)
1739
        diff = diff + 150;
1740

1741 1742 1743 1744
      LOG_I(HW,"eNB Frame %d, time %llu: slot %d, hw_slot %d, diff %d\n",frame, rt_get_time_ns(), slot, hw_slot, diff);
    }

    if (((slot%2==0) && (diff < (-14))) || ((slot%2==1) && (diff < (-7)))) {
1745

1746 1747 1748 1749
      // at the eNB, even slots have double as much time since most of the processing is done here and almost nothing in odd slots
      LOG_W(HW,"eNB Frame %d, time %llu: missed slot %d, proceeding with next one (slot %d, hw_slot %d, mbox_current %d, mbox_target %d, diff %d)\n",
	    frame, rt_get_time_ns(), num_missed_slots, slot, hw_slot, mbox_current,mbox_target, diff);
      
1750
      if (exit_missed_slots==1) {
1751 1752
        stop_meas(&softmodem_stats_mt);
        exit_fun("[HW][eNB] missed slot");
1753
      } else {
1754
        num_missed_slots++;
1755
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_MISSED_SLOTS_ENB,num_missed_slots );
1756
      }
1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778

      if ((slot&1) == 1) {
	for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++){
	  if (PHY_vars_eNB_g[0][CC_id]->proc[((slot>>1)+1)%10].frame_rx==1023)
	    PHY_vars_eNB_g[0][CC_id]->proc[((slot>>1)+1)%10].frame_rx=0;
	  else 
	    PHY_vars_eNB_g[0][CC_id]->proc[((slot>>1)+1)%10].frame_rx += 1;
	  
	  if (PHY_vars_eNB_g[0][CC_id]->proc[((slot>>1)+1)%10].frame_tx==1023)
	    PHY_vars_eNB_g[0][CC_id]->proc[((slot>>1)+1)%10].frame_tx=0;
	  else 
	    PHY_vars_eNB_g[0][CC_id]->proc[((slot>>1)+1)%10].frame_tx += 1;
	}
      }
      
     slot++;
     if (slot == 20) {
       frame++;
       slot = 0;
     }

    
1779
    }
1780

1781
    if (diff>8)
1782 1783
      LOG_D(HW,"eNB Frame %d, time %llu: skipped slot, waiting for hw to catch up (slot %d, hw_slot %d, mbox_current %d, mbox_target %d, diff %d)\n",frame, rt_get_time_ns(), slot, hw_slot, mbox_current,
            mbox_target, diff);
1784

1785 1786
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX, *DAQ_MBOX);
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DIFF, diff);
1787 1788

    delay_cnt = 0;
1789

1790 1791 1792 1793
    while ((diff>0) && (!oai_exit)) {
      time_in = rt_get_time_ns();
      //LOG_D(HW,"eNB Frame %d delaycnt %d : hw_slot %d (%d), slot %d, (slot+1)*15=%d, diff %d, time %llu\n",frame,delay_cnt,hw_slot,((unsigned int *)DAQ_MBOX)[0],slot,(((slot+1)*15)>>1),diff,time_in);
      //LOG_D(HW,"eNB Frame %d, time %llu: sleeping for %llu (slot %d, hw_slot %d, diff %d, mbox %d, delay_cnt %d)\n", frame, time_in, diff*DAQ_PERIOD,slot,hw_slot,diff,((volatile unsigned int *)DAQ_MBOX)[0],delay_cnt);
1794
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP,1);
1795
      ret = rt_sleep_ns(diff*DAQ_PERIOD);
1796 1797
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP,0);
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX, *DAQ_MBOX);
1798

1799 1800
      if (ret)
        LOG_D(HW,"eNB Frame %d, time %llu: rt_sleep_ns returned %d\n",frame, time_in);
1801

Raymond Knopp's avatar
 
Raymond Knopp committed
1802
      hw_slot = (((((volatile unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15;
1803 1804 1805
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME, hw_slot>>1);
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME, frame);
//LOG_D(HW,"eNB Frame %d : hw_slot %d, time %llu\n",frame,hw_slot,rt_get_time_ns());
1806
      delay_cnt++;
1807

1808 1809 1810 1811 1812
      if (delay_cnt == 10) {
        stop_meas(&softmodem_stats_mt);
        LOG_D(HW,"eNB Frame %d: HW stopped ... \n",frame);
        exit_fun("[HW][eNB] HW stopped");
      }
1813

Raymond Knopp's avatar
 
Raymond Knopp committed
1814
      mbox_current = ((volatile unsigned int *)DAQ_MBOX)[0];
1815

Raymond Knopp's avatar
 
Raymond Knopp committed
1816
      if ((mbox_current>=135) && (mbox_target<15)) //handle the frame wrap-arround
1817
        diff = 150-mbox_current+mbox_target;
Raymond Knopp's avatar
 
Raymond Knopp committed
1818
      else if ((mbox_current<15) && (mbox_target>=135))
1819
        diff = -150+mbox_target-mbox_current;
Raymond Knopp's avatar
 
Raymond Knopp committed
1820
      else
1821 1822
        diff = mbox_target - mbox_current;
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1823

1824
#else  // EXMIMO
1825 1826
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME, hw_subframe );
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME, frame );
1827
    tx_launched = 0;
1828

1829
    while (rx_pos < ((1+hw_subframe)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti)) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1830

1831
      unsigned int rxs;
Raymond Knopp's avatar
 
Raymond Knopp committed
1832
#ifndef USRP_DEBUG
1833 1834 1835
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 );
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TXCNT, tx_pos );
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RXCNT, rx_pos );
Raymond Knopp's avatar
 
Raymond Knopp committed
1836

1837
      clock_gettime( CLOCK_MONOTONIC, &trx_time0 );
1838

1839
       start_meas( &softmodem_stats_hw );
1840

1841
      openair0_timestamp timestamp;
1842 1843
      int i=0;
      // prepare rx buffer pointers
1844
      for (i=0; i<PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx; i++)
1845 1846 1847 1848 1849 1850 1851
        rxp[i] = (void*)&rxdata[i][rx_pos];
	// check if nsymb_read == spp
	// map antenna port i to the cc_id. Now use the 1:1 mapping
	rxs = openair0.trx_read_func(&openair0,
				     &timestamp,
				     rxp,
				     spp,
1852 1853
				     PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx);
      
1854
      stop_meas( &softmodem_stats_hw );
1855 1856 1857
      if (frame > 50) { 
	  clock_gettime( CLOCK_MONOTONIC, &trx_time1 );
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
1858

navid's avatar
navid committed
1859
      if (frame > 20){ 
1860 1861 1862
	if (rxs != spp)
	  exit_fun( "problem receiving samples" );
      }
1863
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
1864

1865
      // Transmit TX buffer based on timestamp from RX
1866 1867 1868 1869 1870 1871
    
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
      // prepare tx buffer pointers
      for (i=0; i<PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx; i++)
	txp[i] = (void*)&txdata[i][tx_pos];
      // if symb_written < spp ==> error 
navid's avatar
navid committed
1872
      if (frame > 50) {
1873
	openair0.trx_write_func(&openair0,
1874
				(timestamp+(openair0_cfg[card].tx_scheduling_advance)-openair0_cfg[card].tx_sample_advance),
1875 1876 1877 1878
				txp,
				spp,
				PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx,
				1);
navid's avatar
navid committed
1879 1880
      }
      
1881
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, timestamp&0xffffffff );
1882
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp+(openair0_cfg[card].tx_scheduling_advance)-openair0_cfg[card].tx_sample_advance)&0xffffffff );
1883 1884

      stop_meas( &softmodem_stats_mt );
1885 1886 1887 1888 1889 1890
      if (frame > 50) { 
	  clock_gettime( CLOCK_MONOTONIC, &trx_time2 );
	  // BMC: compute time between rx and tx
	  update_difftimes(trx_time1, trx_time2);
      }

1891

1892
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE,0);
1893 1894 1895 1896
#else
      // USRP_DEBUG is active
      rt_sleep_ns(1000000);
#endif
1897 1898 1899 1900 1901 1902
      /* FT configurable tx lauch delay (in slots): txlaunch_wait, txlaunch_wait_slotcount is device specific and 
	 set in the corresponding library (with txlaunch_wait=1 and txlaunch_wait_slotcount=1 the check is as it previously was) */
      /* old check:
	 if ((frame>50) &&
	 (tx_launched == 0) &&
	 (rx_pos >= (((2*hw_subframe)+1)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))) {*/
Aikaterini's avatar
Aikaterini committed
1903
      if ( (frame>50) && (tx_launched == 0) &&
1904 1905
	   ((openair0_cfg[card].txlaunch_wait == 0) ||
	    ((openair0_cfg[card].txlaunch_wait == 1) &&
1906
	     (rx_pos >= (((2*hw_subframe)+openair0_cfg[card].txlaunch_wait_slotcount)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))))) { 
1907
	
1908
        tx_launched = 1;
1909

1910
        for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938
          if (pthread_mutex_lock(&PHY_vars_eNB_g[0][CC_id]->proc[hw_subframe].mutex_tx) != 0) {
            LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB TX thread %d (IC %d)\n", hw_subframe, PHY_vars_eNB_g[0][CC_id]->proc[hw_subframe].instance_cnt_tx );
            exit_fun( "error locking mutex_tx" );
            break;
          }

          int cnt_tx = ++PHY_vars_eNB_g[0][CC_id]->proc[hw_subframe].instance_cnt_tx;

          pthread_mutex_unlock( &PHY_vars_eNB_g[0][CC_id]->proc[hw_subframe].mutex_tx );

          if (cnt_tx == 0) {
            // the thread was presumably waiting where it should and can now be woken up
            if (pthread_cond_signal(&PHY_vars_eNB_g[0][CC_id]->proc[hw_subframe].cond_tx) != 0) {
              LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TX thread %d\n", hw_subframe );
              exit_fun( "ERROR pthread_cond_signal" );
              break;
            }
          } else {
            LOG_W( PHY,"[eNB] Frame %d, eNB TX thread %d busy!! (rx_cnt %u, cnt_tx %i)\n", PHY_vars_eNB_g[0][CC_id]->proc[hw_subframe].frame_tx, hw_subframe, rx_pos, cnt_tx );
            exit_fun( "TX thread busy" );
            break;
          }
        }
      }

      rx_pos += spp;
      tx_pos += spp;

1939 1940
      if (tx_pos >= openair0_cfg[card].samples_per_frame)
        tx_pos -= openair0_cfg[card].samples_per_frame;
1941 1942
    }

1943 1944
    if (rx_pos >= openair0_cfg[card].samples_per_frame)
      rx_pos -= openair0_cfg[card].samples_per_frame;
1945

Raymond Knopp's avatar
 
Raymond Knopp committed
1946 1947

#endif // USRP
1948

1949
    if (oai_exit) break;
Raymond Knopp's avatar
 
Raymond Knopp committed
1950

1951 1952 1953 1954 1955
    timing_info.time_last = timing_info.time_now;
    timing_info.time_now = rt_get_time_ns();

    if (timing_info.n_samples>0) {
      RTIME time_diff = timing_info.time_now - timing_info.time_last;
1956

1957 1958
      if (time_diff < timing_info.time_min)
        timing_info.time_min = time_diff;
1959

1960 1961
      if (time_diff > timing_info.time_max)
        timing_info.time_max = time_diff;
1962

1963 1964 1965 1966 1967 1968
      timing_info.time_avg += time_diff;
    }

    timing_info.n_samples++;

    if ((slot&1) == 1) {
1969
      // odd slot
1970
#ifdef EXMIMO
1971
      int sf = ((slot>>1)+1)%10;
Raymond Knopp's avatar
 
Raymond Knopp committed
1972
#else
1973
      int sf = hw_subframe;
Raymond Knopp's avatar
 
Raymond Knopp committed
1974
#endif
1975 1976
      if (frame>50) {
	for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1977
#ifdef EXMIMO
1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992
	  
	  if (pthread_mutex_lock(&PHY_vars_eNB_g[0][CC_id]->proc[sf].mutex_tx) != 0) {
	    LOG_E(PHY,"[eNB] ERROR pthread_mutex_lock for eNB TX thread %d (IC %d)\n",sf,PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_tx);
	  } else {
	    //          LOG_I(PHY,"[eNB] Waking up eNB process %d (IC %d)\n",sf,PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt);
	    PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_tx++;
	    pthread_mutex_unlock(&PHY_vars_eNB_g[0][CC_id]->proc[sf].mutex_tx);
	    
	    if (PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_tx == 0) {
	      if (pthread_cond_signal(&PHY_vars_eNB_g[0][CC_id]->proc[sf].cond_tx) != 0) {
		LOG_E(PHY,"[eNB] ERROR pthread_cond_signal for eNB TX thread %d\n",sf);
		exit_fun("nothing to add");
	      }
	    } else {
	      LOG_W(PHY,"[eNB] Frame %d, eNB TX thread %d busy!!\n",PHY_vars_eNB_g[0][CC_id]->proc[sf].frame_tx,sf);
1993
	      exit_fun("nothing to add");
1994 1995 1996
	    }
	  }
	  
Raymond Knopp's avatar
 
Raymond Knopp committed
1997 1998
#endif

1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021
	  if (pthread_mutex_lock(&PHY_vars_eNB_g[0][CC_id]->proc[sf].mutex_rx) != 0) {
	    LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB RX thread %d (IC %d)\n", sf, PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_rx );
	    exit_fun( "error locking mutex_rx" );
	    break;
	  }
	  
	  int cnt_rx = ++PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_rx;
	  
	  pthread_mutex_unlock( &PHY_vars_eNB_g[0][CC_id]->proc[sf].mutex_rx );
	  
	  if (cnt_rx == 0) {
	    // the thread was presumably waiting where it should and can now be woken up
	    if (pthread_cond_signal(&PHY_vars_eNB_g[0][CC_id]->proc[sf].cond_rx) != 0) {
	      LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB RX thread %d\n", sf );
	      exit_fun( "ERROR pthread_cond_signal" );
	      break;
	    }
	  } else {
	    LOG_W( PHY, "[eNB] Frame %d, eNB RX thread %d busy!! instance_cnt %d CC_id %d\n", PHY_vars_eNB_g[0][CC_id]->proc[sf].frame_rx, sf, PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_rx, CC_id );
	    exit_fun( "RX thread busy" );
	    break;
	  }
	}
Raymond Knopp's avatar
 
Raymond Knopp committed
2022
      }
2023 2024 2025 2026
    }

#ifdef EXMIMO
    slot++;
2027

2028 2029 2030 2031
    if (slot == 20) {
      frame++;
      slot = 0;
    }
2032

Raymond Knopp's avatar
 
Raymond Knopp committed
2033
#else
2034 2035
    hw_subframe++;
    slot += 2;
2036

2037
    if (hw_subframe == NUM_ENB_THREADS) {
2038
      // the radio frame is complete, start over
2039 2040 2041 2042
      hw_subframe = 0;
      frame++;
      slot = 1;
    }
2043 2044

#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2045

2046
#if defined(ENABLE_ITTI)
2047
    itti_update_lte_time( frame, slot );
2048
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2049
  }
2050 2051

eNB_thread_cleanup:
Raymond Knopp's avatar
 
Raymond Knopp committed
2052
#ifdef DEBUG_THREADS
2053
  printf( "eNB_thread: finished, ran %d times.\n", frame );
Raymond Knopp's avatar
 
Raymond Knopp committed
2054
#endif
2055

2056
#ifdef HARD_RT
Raymond Knopp's avatar
 
Raymond Knopp committed
2057
  rt_make_soft_real_time();
2058 2059
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
2060
#ifdef DEBUG_THREADS
2061
  printf( "Exiting eNB_thread ..." );
Raymond Knopp's avatar
 
Raymond Knopp committed
2062 2063
#endif
  // clean task
2064
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
2065
  rt_task_delete(task);
2066
#endif
2067 2068

  eNB_thread_status = 0;
2069

2070
  // print_difftimes();
2071

2072
  return &eNB_thread_status;
Raymond Knopp's avatar
 
Raymond Knopp committed
2073
}
2074

2075

Raymond Knopp's avatar
 
Raymond Knopp committed
2076

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2077

2078 2079
static void get_options (int argc, char **argv)
{
2080 2081 2082
  int c;
  //  char                          line[1000];
  //  int                           l;
2083
  int k,i;//,j,k;
2084
#if defined(OAI_USRP) || defined(CPRIGW)
2085
  int clock_src;
2086
#endif
2087 2088 2089 2090 2091
  int CC_id;
#ifdef EXMIMO
  char rxg_fname[256], line[1000];
  FILE *rxg_fd;
  int l;
2092
#endif
2093 2094 2095



2096 2097

  const Enb_properties_array_t *enb_properties;
2098

2099 2100 2101 2102 2103 2104 2105
  enum long_option_e {
    LONG_OPTION_START = 0x100, /* Start after regular single char options */
    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,
2106
    LONG_OPTION_NO_L2_CONNECT,
Raymond Knopp's avatar
 
Raymond Knopp committed
2107
    LONG_OPTION_CALIB_PRACH_TX,
2108 2109
    LONG_OPTION_RXGAIN,
    LONG_OPTION_TXGAIN,
2110
    LONG_OPTION_SCANCARRIER,
2111 2112 2113
    LONG_OPTION_MAXPOWER,
    LONG_OPTION_DUMP_FRAME,
    LONG_OPTION_LOOPMEMORY
2114
  };
2115

2116 2117 2118 2119 2120 2121 2122
  static const struct option long_options[] = {
    {"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},
Raymond Knopp's avatar
 
Raymond Knopp committed
2123 2124 2125 2126
    {"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},
2127
    {"ue-max-power",   required_argument,  NULL, LONG_OPTION_MAXPOWER},
2128 2129
    {"ue-dump-frame", no_argument, NULL, LONG_OPTION_DUMP_FRAME},
    {"loop-memory", required_argument, NULL, LONG_OPTION_LOOPMEMORY},
2130 2131 2132
    {NULL, 0, NULL, 0}
  };

2133
  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) {
2134
    switch (c) {
2135 2136 2137 2138 2139
    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];

2140 2141 2142 2143
    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;
2144

2145 2146 2147 2148 2149
    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;
2150

2151 2152 2153 2154
    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);
Raymond Knopp's avatar
 
Raymond Knopp committed
2155
      break;
2156

2157 2158 2159 2160 2161
    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;
2162

2163 2164 2165
    case LONG_OPTION_DEBUG_UE_PRACH:
      mode = debug_prach;
      break;
2166

2167 2168 2169
    case LONG_OPTION_NO_L2_CONNECT:
      mode = no_L2_connect;
      break;
2170

Raymond Knopp's avatar
 
Raymond Knopp committed
2171 2172 2173 2174
    case LONG_OPTION_CALIB_PRACH_TX:
      mode = calib_prach_tx;
      break;

2175
    case LONG_OPTION_RXGAIN:
2176 2177
      for (i=0; i<4; i++)
        rx_gain[0][i] = atof(optarg);
2178

2179
      break;
2180

2181 2182 2183
    case LONG_OPTION_TXGAIN:
      for (i=0; i<4; i++)
        tx_gain[0][i] = atof(optarg);
2184

2185
      break;
2186

2187 2188 2189 2190 2191
    case LONG_OPTION_SCANCARRIER:
      UE_scan_carrier=1;

      break;

2192 2193 2194 2195 2196 2197 2198 2199
    case LONG_OPTION_LOOPMEMORY:
      mode=loop_through_memory;
      input_fd = fopen(optarg,"r");
      AssertFatal(input_fd != NULL,"Please provide an input file\n");
      break;

   case LONG_OPTION_DUMP_FRAME:
     mode = rx_dump_frame;
2200
     break;   
2201 2202 2203 2204
    case 'A':
      timing_advance = atoi (optarg);
      break;

2205
    case 'C':
2206 2207 2208 2209 2210 2211
      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]);
2212
      }
2213

2214
      UE_scan=0;
2215

2216
      break;
2217

Florian Kaltenberger's avatar
Florian Kaltenberger committed
2218 2219 2220 2221
    case 'a':
      chain_offset = atoi(optarg);
      break;

2222 2223 2224 2225
    case 'd':
#ifdef XFORMS
      do_forms=1;
      printf("Running with XFORMS!\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2226
#endif
2227
      break;
2228 2229 2230 2231
      
    case 'E':
      threequarter_fs=1;
      break;
2232

2233 2234 2235
    case 'K':
#if defined(ENABLE_ITTI)
      itti_dump_file = strdup(optarg);
2236
#else
2237
      printf("-K option is disabled when ENABLE_ITTI is not defined\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2238
#endif
2239
      break;
2240

2241 2242 2243
    case 'O':
      conf_config_file_name = optarg;
      break;
2244

2245 2246 2247
    case 'U':
      UE_flag = 1;
      break;
2248

2249 2250 2251
    case 'm':
      target_dl_mcs = atoi (optarg);
      break;
2252

2253 2254 2255
    case 't':
      target_ul_mcs = atoi (optarg);
      break;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2256
#ifdef OPENAIR2
2257

2258 2259 2260 2261 2262 2263 2264
    case 'W':
      opt_enabled=1;
      opt_type = OPT_WIRESHARK;
      strncpy(in_ip, "127.0.0.1", sizeof(in_ip));
      in_ip[sizeof(in_ip) - 1] = 0; // terminate string
      printf("Enabling OPT for wireshark for local interface");
      /*
2265 2266 2267
      if (optarg == NULL){
      in_ip[0] =NULL;
      printf("Enabling OPT for wireshark for local interface");
2268
      } else {
2269 2270 2271
      strncpy(in_ip, optarg, sizeof(in_ip));
      in_ip[sizeof(in_ip) - 1] = 0; // terminate string
      printf("Enabling OPT for wireshark with %s \n",in_ip);
2272 2273 2274
      }
      */
      break;
2275

2276
    case 'P':
2277 2278
      opt_type = OPT_PCAP;
      opt_enabled=1;
2279 2280 2281 2282 2283

      if (optarg == NULL) {
        strncpy(in_path, "/tmp/oai_opt.pcap", sizeof(in_path));
        in_path[sizeof(in_path) - 1] = 0; // terminate string
        printf("Enabling OPT for PCAP with the following path /tmp/oai_opt.pcap");
2284
      } else {
2285 2286 2287
        strncpy(in_path, optarg, sizeof(in_path));
        in_path[sizeof(in_path) - 1] = 0; // terminate string
        printf("Enabling OPT for PCAP  with the following file %s \n",in_path);
2288
      }
2289 2290

      break;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2291
#endif
2292

Raymond Knopp's avatar
 
Raymond Knopp committed
2293 2294 2295
    case 'V':
      ouput_vcd = 1;
      break;
2296

Raymond Knopp's avatar
 
Raymond Knopp committed
2297
    case  'q':
Raymond Knopp's avatar
 
Raymond Knopp committed
2298 2299
      opp_enabled = 1;
      break;
2300

Raymond Knopp's avatar
 
Raymond Knopp committed
2301 2302 2303
    case  'R' :
      online_log_messages =1;
      break;
2304

Raymond Knopp's avatar
 
Raymond Knopp committed
2305
    case 'r':
2306
      UE_scan = 0;
2307

2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
        switch(atoi(optarg)) {
        case 6:
          frame_parms[CC_id]->N_RB_DL=6;
          frame_parms[CC_id]->N_RB_UL=6;
          break;

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

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

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

        default:
          printf("Unknown N_RB_DL %d, switching to 25\n",atoi(optarg));
          break;
        }
Raymond Knopp's avatar
 
Raymond Knopp committed
2334
      }
2335

2336
      break;
2337

Raymond Knopp's avatar
 
Raymond Knopp committed
2338
    case 's':
2339
#if defined(OAI_USRP) || defined(CPRIGW)
Raymond Knopp's avatar
 
Raymond Knopp committed
2340 2341

      clock_src = atoi(optarg);
2342

Raymond Knopp's avatar
 
Raymond Knopp committed
2343
      if (clock_src == 0) {
2344 2345 2346 2347 2348
        //  char ref[128] = "internal";
        //strncpy(uhd_ref, ref, strlen(ref)+1);
      } else if (clock_src == 1) {
        //char ref[128] = "external";
        //strncpy(uhd_ref, ref, strlen(ref)+1);
Raymond Knopp's avatar
 
Raymond Knopp committed
2349
      }
2350

Raymond Knopp's avatar
 
Raymond Knopp committed
2351 2352 2353 2354
#else
      printf("Note: -s not defined for ExpressMIMO2\n");
#endif
      break;
2355

2356 2357 2358 2359
    case 'S':
      exit_missed_slots=0;
      printf("Skip exit for missed slots\n");
      break;
2360

2361
    case 'g':
Raymond Knopp's avatar
 
Raymond Knopp committed
2362
      glog_level=atoi(optarg); // value between 1 - 9
2363
      break;
2364 2365

    case 'F':
2366
#ifdef EXMIMO
2367 2368
      sprintf(rxg_fname,"%srxg.lime",optarg);
      rxg_fd = fopen(rxg_fname,"r");
2369

2370
      if (rxg_fd) {
2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388
        printf("Loading RX Gain parameters from %s\n",rxg_fname);
        l=0;

        while (fgets(line, sizeof(line), rxg_fd)) {
          if ((strlen(line)==0) || (*line == '#')) continue; //ignore empty or comment lines
          else {
            if (l==0) sscanf(line,"%d %d %d %d",&rxg_max[0],&rxg_max[1],&rxg_max[2],&rxg_max[3]);

            if (l==1) sscanf(line,"%d %d %d %d",&rxg_med[0],&rxg_med[1],&rxg_med[2],&rxg_med[3]);

            if (l==2) sscanf(line,"%d %d %d %d",&rxg_byp[0],&rxg_byp[1],&rxg_byp[2],&rxg_byp[3]);

            l++;
          }
        }
      } else
        printf("%s not found, running with defaults\n",rxg_fname);

2389
#endif
2390
      break;
2391

2392 2393 2394
    case 'G':
      glog_verbosity=atoi(optarg);// value from 0, 0x5, 0x15, 0x35, 0x75
      break;
2395

2396 2397
    case 'x':
      transmission_mode = atoi(optarg);
2398

2399
      if (transmission_mode > 2) {
2400 2401
        printf("Transmission mode > 2 (%d) not supported for the moment\n",transmission_mode);
        exit(-1);
2402
      }
2403
      break;
2404

2405 2406 2407
    case 'T':
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) 
	frame_parms[CC_id]->frame_type = TDD;
2408
      break;
2409

2410 2411 2412 2413
    case 'h':
      help ();
      exit (-1);
       
Raymond Knopp's avatar
 
Raymond Knopp committed
2414
    default:
2415 2416
      help ();
      exit (-1);
Raymond Knopp's avatar
 
Raymond Knopp committed
2417
      break;
2418 2419
    }
  }
2420

Raymond Knopp's avatar
 
Raymond Knopp committed
2421 2422
  if (UE_flag == 0)
    AssertFatal(conf_config_file_name != NULL,"Please provide a configuration file\n");
2423 2424


Raymond Knopp's avatar
 
Raymond Knopp committed
2425
  if ((UE_flag == 0) && (conf_config_file_name != NULL)) {
2426
    int i,j;
2427

Raymond Knopp's avatar
 
Raymond Knopp committed
2428
    NB_eNB_INST = 1;
2429

Raymond Knopp's avatar
 
Raymond Knopp committed
2430 2431
    /* Read eNB configuration file */
    enb_properties = enb_config_init(conf_config_file_name);
2432

Raymond Knopp's avatar
 
Raymond Knopp committed
2433
    AssertFatal (NB_eNB_INST <= enb_properties->number,
2434 2435
                 "Number of eNB is greater than eNB defined in configuration file %s (%d/%d)!",
                 conf_config_file_name, NB_eNB_INST, enb_properties->number);
2436

Raymond Knopp's avatar
 
Raymond Knopp committed
2437
    /* Update some simulation parameters */
2438
    for (i=0; i < enb_properties->number; i++) {
2439
      AssertFatal (MAX_NUM_CCs == enb_properties->properties[i]->nb_cc,
2440 2441 2442
                   "lte-softmodem compiled with MAX_NUM_CCs=%d, but only %d CCs configured for eNB %d!",
                   MAX_NUM_CCs, enb_properties->properties[i]->nb_cc, i);

2443 2444
      for (j=0; j<enb_properties->properties[i]->nb_rrh_gw; j++) {
	
2445 2446 2447 2448 2449
	if (enb_properties->properties[i]->rrh_gw_config[j].active == 1 ) {
	  local_remote_radio = BBU_REMOTE_RADIO_HEAD;
	  eth_params = (eth_params_t*)malloc(sizeof(eth_params_t));
	  memset(eth_params, 0, sizeof(eth_params_t));
	 
2450 2451 2452 2453 2454 2455 2456
	  printf( "\n\tRRH GW %d config for eNB %u:\n\n", j, i);
	  printf( "\tinterface name :       \t%s:\n",enb_properties->properties[i]->rrh_gw_if_name);
	  printf( "\tlocal address  :       \t%s:\n",enb_properties->properties[i]->rrh_gw_config[j].local_address);
	  printf( "\tlocal port     :       \t%d:\n",enb_properties->properties[i]->rrh_gw_config[j].local_port);
	  printf( "\tremote address :       \t%s:\n",enb_properties->properties[i]->rrh_gw_config[j].remote_address);
	  printf( "\tremote port    :       \t%d:\n",enb_properties->properties[i]->rrh_gw_config[j].remote_port);
	  printf( "\ttransport      :       \t%s Ethernet:\n\n",(enb_properties->properties[i]->rrh_gw_config[j].raw == 1)? "RAW" : "UDP");
2457 2458 2459 2460 2461 2462 2463 2464 2465 2466
	  
	  eth_params->local_if_name             = enb_properties->properties[i]->rrh_gw_if_name;
	  eth_params->my_addr                   = enb_properties->properties[i]->rrh_gw_config[j].local_address;
	  eth_params->my_port                   = enb_properties->properties[i]->rrh_gw_config[j].local_port;
	  eth_params->remote_addr               = enb_properties->properties[i]->rrh_gw_config[j].remote_address;
	  eth_params->remote_port               = enb_properties->properties[i]->rrh_gw_config[j].remote_port;
	  eth_params->transp_preference         = enb_properties->properties[i]->rrh_gw_config[j].raw;
 
	} else {
	  local_remote_radio = BBU_LOCAL_RADIO_HEAD; 
2467 2468 2469 2470
	}
	
      }

2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
        frame_parms[CC_id]->frame_type =       enb_properties->properties[i]->frame_type[CC_id];
        frame_parms[CC_id]->tdd_config =       enb_properties->properties[i]->tdd_config[CC_id];
        frame_parms[CC_id]->tdd_config_S =     enb_properties->properties[i]->tdd_config_s[CC_id];
        frame_parms[CC_id]->Ncp =              enb_properties->properties[i]->prefix_type[CC_id];

        //for (j=0; j < enb_properties->properties[i]->nb_cc; j++ ){
        frame_parms[CC_id]->Nid_cell            =  enb_properties->properties[i]->Nid_cell[CC_id];
        frame_parms[CC_id]->N_RB_DL             =  enb_properties->properties[i]->N_RB_DL[CC_id];
        frame_parms[CC_id]->N_RB_UL             =  enb_properties->properties[i]->N_RB_DL[CC_id];
        frame_parms[CC_id]->nb_antennas_tx      =  enb_properties->properties[i]->nb_antennas_tx[CC_id];
        frame_parms[CC_id]->nb_antennas_tx_eNB  =  enb_properties->properties[i]->nb_antennas_tx[CC_id];
        frame_parms[CC_id]->nb_antennas_rx      =  enb_properties->properties[i]->nb_antennas_rx[CC_id];
        //} // j
Raymond Knopp's avatar
 
Raymond Knopp committed
2485 2486
      }

2487

2488
#ifdef OPENAIR2
2489

2490 2491 2492
      init_all_otg(0);
      g_otg->seed = 0;
      init_seeds(g_otg->seed);
2493 2494 2495 2496 2497 2498 2499 2500 2501 2502

      for (k=0; k<enb_properties->properties[i]->num_otg_elements; k++) {
        j=enb_properties->properties[i]->otg_ue_id[k]; // ue_id
        g_otg->application_idx[i][j] = 1;
        //g_otg->packet_gen_type=SUBSTRACT_STRING;
        g_otg->background[i][j][0] =enb_properties->properties[i]->otg_bg_traffic[k];
        g_otg->application_type[i][j][0] =enb_properties->properties[i]->otg_app_type[k];// BCBR; //MCBR, BCBR

        printf("[OTG] configuring traffic type %d for  eNB %d UE %d (Background traffic is %s)\n",
               g_otg->application_type[i][j][0], i, j,(g_otg->background[i][j][0]==1)?"Enabled":"Disabled");
2503
      }
2504

2505
      init_predef_traffic(enb_properties->properties[i]->num_otg_elements, 1);
2506

2507
#endif
2508

2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522
      glog_level                     = enb_properties->properties[i]->glog_level;
      glog_verbosity                 = enb_properties->properties[i]->glog_verbosity;
      hw_log_level                   = enb_properties->properties[i]->hw_log_level;
      hw_log_verbosity               = enb_properties->properties[i]->hw_log_verbosity ;
      phy_log_level                  = enb_properties->properties[i]->phy_log_level;
      phy_log_verbosity              = enb_properties->properties[i]->phy_log_verbosity;
      mac_log_level                  = enb_properties->properties[i]->mac_log_level;
      mac_log_verbosity              = enb_properties->properties[i]->mac_log_verbosity;
      rlc_log_level                  = enb_properties->properties[i]->rlc_log_level;
      rlc_log_verbosity              = enb_properties->properties[i]->rlc_log_verbosity;
      pdcp_log_level                 = enb_properties->properties[i]->pdcp_log_level;
      pdcp_log_verbosity             = enb_properties->properties[i]->pdcp_log_verbosity;
      rrc_log_level                  = enb_properties->properties[i]->rrc_log_level;
      rrc_log_verbosity              = enb_properties->properties[i]->rrc_log_verbosity;
Lionel Gauthier's avatar
 
Lionel Gauthier committed
2523 2524 2525 2526 2527 2528
# if defined(ENABLE_USE_MME)
      gtpu_log_level                 = enb_properties->properties[i]->gtpu_log_level;
      gtpu_log_verbosity             = enb_properties->properties[i]->gtpu_log_verbosity;
      udp_log_level                  = enb_properties->properties[i]->udp_log_level;
      udp_log_verbosity              = enb_properties->properties[i]->udp_log_verbosity;
#endif
2529 2530 2531
#if defined (ENABLE_SECURITY)
      osa_log_level                  = enb_properties->properties[i]->osa_log_level;
      osa_log_verbosity              = enb_properties->properties[i]->osa_log_verbosity;
2532
#endif
Florian Kaltenberger's avatar
Florian Kaltenberger committed
2533

Raymond Knopp's avatar
 
Raymond Knopp committed
2534
      // adjust the log
2535
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
2536 2537 2538 2539 2540 2541 2542 2543 2544 2545
        for (k = 0 ; k < 4; k++) {
          downlink_frequency[CC_id][k]      =       enb_properties->properties[i]->downlink_frequency[CC_id];
          uplink_frequency_offset[CC_id][k] =  enb_properties->properties[i]->uplink_frequency_offset[CC_id];
          rx_gain[CC_id][k]                 =  (double)enb_properties->properties[i]->rx_gain[CC_id];
          tx_gain[CC_id][k]                 =  (double)enb_properties->properties[i]->tx_gain[CC_id];
        }

        printf("Downlink frequency/ uplink offset of CC_id %d set to %ju/%d\n", CC_id,
               enb_properties->properties[i]->downlink_frequency[CC_id],
               enb_properties->properties[i]->uplink_frequency_offset[CC_id]);
Raymond Knopp's avatar
 
Raymond Knopp committed
2546
      } // CC_id
2547
    }// i
2548 2549 2550 2551 2552 2553 2554 2555
  } else if (UE_flag == 1) {
    if (conf_config_file_name != NULL) {
      
      // Here the configuration file is the XER encoded UE capabilities
      // Read it in and store in asn1c data structures
      strcpy(uecap_xer,conf_config_file_name);
      uecap_xer_in=1;
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
2556
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
2557
}
2558

2559 2560
int main( int argc, char **argv )
{
2561
  int i,aa,card=0;
Lionel Gauthier's avatar
Lionel Gauthier committed
2562
#if defined (XFORMS) || defined (EMOS) || defined (EXMIMO)
Raymond Knopp's avatar
 
Raymond Knopp committed
2563
  void *status;
2564
#endif
2565

Raymond Knopp's avatar
 
Raymond Knopp committed
2566
  int CC_id;
Raymond Knopp's avatar
 
Raymond Knopp committed
2567
  uint16_t Nid_cell = 0;
2568
  uint8_t  cooperation_flag=0,  abstraction_flag=0;
2569
#ifndef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
2570
  uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2;
2571 2572 2573
#endif

#ifdef ENABLE_TCXO
Raymond Knopp's avatar
 
Raymond Knopp committed
2574
  unsigned int tcxo = 114;
2575 2576
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
2577
#if defined (XFORMS)
2578 2579
  int ret;
#endif
2580
#if defined (EMOS) || (! defined (RTAI))
Raymond Knopp's avatar
 
Raymond Knopp committed
2581
  int error_code;
2582
#endif
2583

2584 2585 2586 2587 2588
#ifdef DEBUG_CONSOLE
  setvbuf(stdout, NULL, _IONBF, 0);
  setvbuf(stderr, NULL, _IONBF, 0);
#endif

2589 2590 2591
  PHY_VARS_UE *UE[MAX_NUM_CCs];

  mode = normal_txrx;
2592
  memset(&openair0_cfg[0],0,sizeof(openair0_config_t)*MAX_CARDS);
2593

2594
  memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
Raymond Knopp's avatar
 
Raymond Knopp committed
2595
  set_latency_target();
2596

2597
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2598 2599
    frame_parms[CC_id] = (LTE_DL_FRAME_PARMS*) malloc(sizeof(LTE_DL_FRAME_PARMS));
    /* Set some default values that may be overwritten while reading options */
2600
    frame_parms[CC_id]->frame_type          = FDD;
Raymond Knopp's avatar
 
Raymond Knopp committed
2601 2602
    frame_parms[CC_id]->tdd_config          = 3;
    frame_parms[CC_id]->tdd_config_S        = 0;
2603 2604
    frame_parms[CC_id]->N_RB_DL             = 100;
    frame_parms[CC_id]->N_RB_UL             = 100;
Raymond Knopp's avatar
 
Raymond Knopp committed
2605
    frame_parms[CC_id]->Ncp                 = NORMAL;
Raymond Knopp's avatar
 
Raymond Knopp committed
2606 2607
    frame_parms[CC_id]->Ncp_UL              = NORMAL;
    frame_parms[CC_id]->Nid_cell            = Nid_cell;
Raymond Knopp's avatar
 
Raymond Knopp committed
2608
    frame_parms[CC_id]->num_MBSFN_config    = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2609 2610 2611
    frame_parms[CC_id]->nb_antennas_tx_eNB  = 1;
    frame_parms[CC_id]->nb_antennas_tx      = 1;
    frame_parms[CC_id]->nb_antennas_rx      = 1;
Raymond Knopp's avatar
 
Raymond Knopp committed
2612
  }
2613

2614 2615 2616 2617 2618
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    downlink_frequency[CC_id][0] = 2680000000; // 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];
2619
    //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
2620
  }
2621 2622
  logInit();
 
2623
  get_options (argc, argv); //Command-line options
2624 2625 2626
 
  
  // initialize the log (see log.h for details)
Florian Kaltenberger's avatar
Florian Kaltenberger committed
2627 2628
  set_glog(glog_level, glog_verbosity);

2629 2630
  //randominit (0);
  set_taus_seed (0);
Raymond Knopp's avatar
 
Raymond Knopp committed
2631

2632 2633
  if (UE_flag==1) {
    printf("configuring for UE\n");
2634

2635
    set_comp_log(HW,      LOG_INFO,  LOG_HIGH, 1);
2636 2637 2638 2639 2640 2641
    set_comp_log(PHY,     LOG_INFO,   LOG_HIGH, 1);
    set_comp_log(MAC,     LOG_INFO,   LOG_HIGH, 1);
    set_comp_log(RLC,     LOG_INFO,   LOG_HIGH, 1);
    set_comp_log(PDCP,    LOG_INFO,   LOG_HIGH, 1);
    set_comp_log(OTG,     LOG_INFO,   LOG_HIGH, 1);
    set_comp_log(RRC,     LOG_INFO,   LOG_HIGH, 1);
2642
#if defined(ENABLE_ITTI)
2643
    set_comp_log(EMU,     LOG_INFO,   LOG_MED, 1);
2644
# if defined(ENABLE_USE_MME)
2645
    set_comp_log(NAS,     LOG_INFO,   LOG_HIGH, 1);
2646 2647
# endif
#endif
2648 2649
  } else {
    printf("configuring for eNB\n");
2650

2651
    set_comp_log(HW,      hw_log_level, hw_log_verbosity, 1);
2652
#ifdef OPENAIR2
2653 2654 2655 2656 2657
    set_comp_log(PHY,     phy_log_level,   phy_log_verbosity, 1);

    if (opt_enabled == 1 )
      set_comp_log(OPT,   opt_log_level,      opt_log_verbosity, 1);

2658
#else
2659
    set_comp_log(PHY,     LOG_INFO,   LOG_HIGH, 1);
2660
#endif
2661 2662 2663 2664
    set_comp_log(MAC,     mac_log_level,  mac_log_verbosity, 1);
    set_comp_log(RLC,     rlc_log_level,   rlc_log_verbosity, 1);
    set_comp_log(PDCP,    pdcp_log_level,  pdcp_log_verbosity, 1);
    set_comp_log(RRC,     rrc_log_level,  rrc_log_verbosity, 1);
2665
#if defined(ENABLE_ITTI)
2666
    set_comp_log(EMU,     LOG_INFO,   LOG_MED, 1);
2667
# if defined(ENABLE_USE_MME)
2668 2669 2670 2671
    set_comp_log(UDP_,    udp_log_level,   udp_log_verbosity, 1);
    set_comp_log(GTPU,    gtpu_log_level,   gtpu_log_verbosity, 1);
    set_comp_log(S1AP,    LOG_DEBUG,   LOG_HIGH, 1);
    set_comp_log(SCTP,    LOG_INFO,   LOG_HIGH, 1);
2672
# endif
2673
#if defined(ENABLE_SECURITY)
2674
    set_comp_log(OSA,    osa_log_level,   osa_log_verbosity, 1);
2675
#endif
2676
#endif
2677
#ifdef LOCALIZATION
2678 2679 2680 2681 2682 2683 2684 2685 2686
    set_comp_log(LOCALIZE, LOG_DEBUG, LOG_LOW, 1);
    set_component_filelog(LOCALIZE);
#endif
    set_comp_log(ENB_APP, LOG_INFO, LOG_HIGH, 1);
    set_comp_log(OTG,     LOG_INFO,   LOG_HIGH, 1);

    if (online_log_messages == 1) {
      set_component_filelog(RRC);
      set_component_filelog(PDCP);
Raymond Knopp's avatar
 
Raymond Knopp committed
2687
    }
2688
  }
2689

Raymond Knopp's avatar
 
Raymond Knopp committed
2690 2691
  if (ouput_vcd) {
    if (UE_flag==1)
2692
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_UE.vcd");
Raymond Knopp's avatar
 
Raymond Knopp committed
2693
    else
2694
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_eNB.vcd");
Raymond Knopp's avatar
 
Raymond Knopp committed
2695
  }
2696

2697
  if (opp_enabled ==1){
2698
    reset_opp_meas();
2699 2700
  }
  cpuf=get_cpu_freq_GHz();
2701

2702
#if defined(ENABLE_ITTI)
2703

Raymond Knopp's avatar
 
Raymond Knopp committed
2704 2705
  if (UE_flag == 1) {
    log_set_instance_type (LOG_INSTANCE_UE);
2706
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
2707 2708
    log_set_instance_type (LOG_INSTANCE_ENB);
  }
2709

Raymond Knopp's avatar
 
Raymond Knopp committed
2710
  itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, itti_dump_file);
2711
 
2712 2713
  // initialize mscgen log after ITTI
  MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX);
2714 2715
#endif
 
2716
#ifdef OPENAIR2
2717

2718 2719
  if (opt_type != OPT_NONE) {
    radio_type_t radio_type;
2720

2721 2722
    if (frame_parms[0]->frame_type == FDD)
      radio_type = RADIO_TYPE_FDD;
2723
    else
2724
      radio_type = RADIO_TYPE_TDD;
2725

2726 2727 2728
    if (init_opt(in_path, in_ip, NULL, radio_type) == -1)
      LOG_E(OPT,"failed to run OPT \n");
  }
2729

2730
#endif
2731
#ifdef PDCP_USE_NETLINK
Raymond Knopp's avatar
 
Raymond Knopp committed
2732
  netlink_init();
2733 2734 2735
#if defined(PDCP_USE_NETLINK_QUEUES)
  pdcp_netlink_init();
#endif
2736 2737
#endif

2738
#if !defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
2739 2740 2741
  // to make a graceful exit when ctrl-c is pressed
  signal(SIGSEGV, signal_handler);
  signal(SIGINT, signal_handler);
2742
#endif
2743 2744

#ifndef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
2745 2746 2747 2748
  check_clock();
#endif

  // init the parameters
2749
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2750
    frame_parms[CC_id]->nushift            = 0;
2751

2752 2753 2754 2755 2756 2757 2758 2759 2760
    if (UE_flag==0) {

    } else {
      //UE_flag==1
      frame_parms[CC_id]->nb_antennas_tx     = 1;
      frame_parms[CC_id]->nb_antennas_rx     = 1;
      frame_parms[CC_id]->nb_antennas_tx_eNB = (transmission_mode == 1) ? 1 : 2; //initial value overwritten by initial sync later
    }

Raymond Knopp's avatar
 
Raymond Knopp committed
2761 2762 2763 2764 2765 2766 2767 2768
    frame_parms[CC_id]->mode1_flag         = (transmission_mode == 1) ? 1 : 0;
    frame_parms[CC_id]->phich_config_common.phich_resource = oneSixth;
    frame_parms[CC_id]->phich_config_common.phich_duration = normal;
    // UL RS Config
    frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = 0;//n_DMRS1 set to 0
    frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = 0;
    frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = 0;
    frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0;
2769
    frame_parms[CC_id]->threequarter_fs = threequarter_fs;
2770 2771
    init_ul_hopping(frame_parms[CC_id]);
    init_frame_parms(frame_parms[CC_id],1);
2772 2773
    //   phy_init_top(frame_parms[CC_id]);
    phy_init_lte_top(frame_parms[CC_id]);
Raymond Knopp's avatar
 
Raymond Knopp committed
2774 2775 2776
  }


2777
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2778
    //init prach for openair1 test
2779
    frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22;
Raymond Knopp's avatar
 
Raymond Knopp committed
2780
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1;
2781
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2782 2783 2784
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.highSpeedFlag=0;
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_FreqOffset=0;
    // prach_fmt = get_prach_fmt(frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex, frame_parms->frame_type);
Raymond Knopp's avatar
 
Raymond Knopp committed
2785
    // N_ZC = (prach_fmt <4)?839:139;
Raymond Knopp's avatar
 
Raymond Knopp committed
2786
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
2787 2788

  if (UE_flag==1) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2789 2790 2791
    NB_UE_INST=1;
    NB_INST=1;

Raymond Knopp's avatar
 
Raymond Knopp committed
2792 2793
    PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE**));
    PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_UE*)*MAX_NUM_CCs);
2794 2795

    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
2796 2797 2798 2799

      PHY_vars_UE_g[0][CC_id] = init_lte_UE(frame_parms[CC_id], 0,abstraction_flag,transmission_mode);
      UE[CC_id] = PHY_vars_UE_g[0][CC_id];
      printf("PHY_vars_UE_g[0][%d] = %p\n",CC_id,UE[CC_id]);
Raymond Knopp's avatar
 
Raymond Knopp committed
2800
#ifndef OPENAIR2
2801 2802 2803 2804 2805 2806 2807 2808 2809

      for (i=0; i<NUMBER_OF_CONNECTED_eNB_MAX; i++) {
        UE[CC_id]->pusch_config_dedicated[i].betaOffset_ACK_Index = beta_ACK;
        UE[CC_id]->pusch_config_dedicated[i].betaOffset_RI_Index  = beta_RI;
        UE[CC_id]->pusch_config_dedicated[i].betaOffset_CQI_Index = beta_CQI;

        UE[CC_id]->scheduling_request_config[i].sr_PUCCH_ResourceIndex = 0;
        UE[CC_id]->scheduling_request_config[i].sr_ConfigIndex = 7+(0%3);
        UE[CC_id]->scheduling_request_config[i].dsr_TransMax = sr_n4;
Raymond Knopp's avatar
 
Raymond Knopp committed
2810
      }
2811

2812
#endif
2813 2814 2815


      UE[CC_id]->UE_scan = UE_scan;
2816
      UE[CC_id]->UE_scan_carrier = UE_scan_carrier;
2817 2818 2819
      UE[CC_id]->mode    = mode;

      compute_prach_seq(&UE[CC_id]->lte_frame_parms.prach_config_common,
2820 2821 2822
                        UE[CC_id]->lte_frame_parms.frame_type,
                        UE[CC_id]->X_u);

2823
      UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1234;
2824
#ifndef OPENAIR2
2825
      UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1235;
2826
#endif
2827

2828
#ifdef EXMIMO
2829

2830 2831 2832 2833
      for (i=0; i<4; i++) {
        UE[CC_id]->rx_gain_max[i] = rxg_max[i];
        UE[CC_id]->rx_gain_med[i] = rxg_med[i];
        UE[CC_id]->rx_gain_byp[i] = rxg_byp[i];
Raymond Knopp's avatar
 
Raymond Knopp committed
2834
      }
2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853

      if ((UE[0]->mode == normal_txrx) ||
          (UE[0]->mode == rx_calib_ue) ||
          (UE[0]->mode == no_L2_connect) ||
          (UE[0]->mode == debug_prach)) {
        for (i=0; i<4; i++)
          rx_gain_mode[CC_id][i] = max_gain;

        UE[CC_id]->rx_total_gain_dB =  UE[CC_id]->rx_gain_max[0] + (int)rx_gain[CC_id][0] - 30; //-30 because it was calibrated with a 30dB gain
      } else if ((mode == rx_calib_ue_med)) {
        for (i=0; i<4; i++)
          rx_gain_mode[CC_id][i] =  med_gain;

        UE[CC_id]->rx_total_gain_dB =  UE[CC_id]->rx_gain_med[0]  + (int)rx_gain[CC_id][0] - 30; //-30 because it was calibrated with a 30dB gain;
      } else if ((mode == rx_calib_ue_byp)) {
        for (i=0; i<4; i++)
          rx_gain_mode[CC_id][i] =  byp_gain;

        UE[CC_id]->rx_total_gain_dB =  UE[CC_id]->rx_gain_byp[0]  + (int)rx_gain[CC_id][0] - 30; //-30 because it was calibrated with a 30dB gain;
Raymond Knopp's avatar
 
Raymond Knopp committed
2854
      }
2855

2856
#else
2857
      UE[CC_id]->rx_total_gain_dB =  (int)rx_gain[CC_id][0];
2858
#endif
2859

2860
      UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id];
2861

2862 2863


2864
#ifdef EXMIMO
2865

Raymond Knopp's avatar
 
Raymond Knopp committed
2866
      //N_TA_offset
2867
      if (UE[CC_id]->lte_frame_parms.frame_type == TDD) {
2868 2869 2870 2871 2872 2873 2874 2875
        if (UE[CC_id]->lte_frame_parms.N_RB_DL == 100)
          UE[CC_id]->N_TA_offset = 624;
        else if (UE[CC_id]->lte_frame_parms.N_RB_DL == 50)
          UE[CC_id]->N_TA_offset = 624/2;
        else if (UE[CC_id]->lte_frame_parms.N_RB_DL == 25)
          UE[CC_id]->N_TA_offset = 624/4;
      } else {
        UE[CC_id]->N_TA_offset = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2876
      }
2877

2878
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
2879
      //already taken care of in lte-softmodem
2880
      UE[CC_id]->N_TA_offset = 0;
2881
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2882
    }
2883

Raymond Knopp's avatar
 
Raymond Knopp committed
2884 2885 2886 2887
    openair_daq_vars.manual_timing_advance = 0;
    openair_daq_vars.rx_gain_mode = DAQ_AGC_ON;
    openair_daq_vars.auto_freq_correction = 0;
    openair_daq_vars.use_ia_receiver = 0;
2888 2889 2890



Raymond Knopp's avatar
 
Raymond Knopp committed
2891
    //  printf("tx_max_power = %d -> amp %d\n",tx_max_power,get_tx_amp(tx_max_power,tx_max_power));
2892 2893 2894 2895 2896 2897
  } else {
    //this is eNB
    PHY_vars_eNB_g = malloc(sizeof(PHY_VARS_eNB**));
    PHY_vars_eNB_g[0] = malloc(sizeof(PHY_VARS_eNB*));

    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
2898
      PHY_vars_eNB_g[0][CC_id] = init_lte_eNB(frame_parms[CC_id],0,frame_parms[CC_id]->Nid_cell,cooperation_flag,transmission_mode,abstraction_flag);
2899 2900
      PHY_vars_eNB_g[0][CC_id]->CC_id = CC_id;

2901
#ifndef OPENAIR2
2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917

      for (i=0; i<NUMBER_OF_UE_MAX; i++) {
        PHY_vars_eNB_g[0][CC_id]->pusch_config_dedicated[i].betaOffset_ACK_Index = beta_ACK;
        PHY_vars_eNB_g[0][CC_id]->pusch_config_dedicated[i].betaOffset_RI_Index  = beta_RI;
        PHY_vars_eNB_g[0][CC_id]->pusch_config_dedicated[i].betaOffset_CQI_Index = beta_CQI;

        PHY_vars_eNB_g[0][CC_id]->scheduling_request_config[i].sr_PUCCH_ResourceIndex = i;
        PHY_vars_eNB_g[0][CC_id]->scheduling_request_config[i].sr_ConfigIndex = 7+(i%3);
        PHY_vars_eNB_g[0][CC_id]->scheduling_request_config[i].dsr_TransMax = sr_n4;
      }

#endif

      compute_prach_seq(&PHY_vars_eNB_g[0][CC_id]->lte_frame_parms.prach_config_common,
                        PHY_vars_eNB_g[0][CC_id]->lte_frame_parms.frame_type,
                        PHY_vars_eNB_g[0][CC_id]->X_u);
Raymond Knopp's avatar
 
Raymond Knopp committed
2918

2919
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
2920

2921
      PHY_vars_eNB_g[0][CC_id]->rx_total_gain_eNB_dB = (int)rx_gain[CC_id][0];
Raymond Knopp's avatar
 
Raymond Knopp committed
2922

2923
#else
2924 2925 2926
      PHY_vars_eNB_g[0][CC_id]->rx_total_gain_eNB_dB =  rxg_max[0] + (int)rx_gain[CC_id][0] - 30; //was measured at rxgain=30;

      printf("Setting RX total gain to %d\n",PHY_vars_eNB_g[0][CC_id]->rx_total_gain_eNB_dB);
Raymond Knopp's avatar
 
Raymond Knopp committed
2927

2928 2929 2930
      // set eNB to max gain
      for (i=0; i<4; i++)
        rx_gain_mode[CC_id][i] = max_gain;
Raymond Knopp's avatar
 
Raymond Knopp committed
2931

2932
#endif
2933

2934
#ifdef EXMIMO
2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945

      //N_TA_offset
      if (PHY_vars_eNB_g[0][CC_id]->lte_frame_parms.frame_type == TDD) {
        if (PHY_vars_eNB_g[0][CC_id]->lte_frame_parms.N_RB_DL == 100)
          PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 624;
        else if (PHY_vars_eNB_g[0][CC_id]->lte_frame_parms.N_RB_DL == 50)
          PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 624/2;
        else if (PHY_vars_eNB_g[0][CC_id]->lte_frame_parms.N_RB_DL == 25)
          PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 624/4;
      } else {
        PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2946
      }
2947

2948
#else
2949
      //already taken care of in lte-softmodem.c
2950 2951
      PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 0;
#endif
2952

2953
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
2954 2955


2956 2957 2958 2959 2960 2961 2962 2963 2964
    NB_eNB_INST=1;
    NB_INST=1;

    openair_daq_vars.ue_dl_rb_alloc=0x1fff;
    openair_daq_vars.target_ue_dl_mcs=target_dl_mcs;
    openair_daq_vars.ue_ul_nb_rb=6;
    openair_daq_vars.target_ue_ul_mcs=target_ul_mcs;

  }
2965 2966 2967 2968
#ifndef RTAI
  fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx);
  cpuf=get_cpu_freq_GHz();
#endif 
2969

Raymond Knopp's avatar
 
Raymond Knopp committed
2970
  dump_frame_parms(frame_parms[0]);
2971

2972 2973 2974
  for (card=0; card<MAX_CARDS; card++) {

    if(frame_parms[0]->N_RB_DL == 100) {
2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986
      if (frame_parms[0]->threequarter_fs) {
	openair0_cfg[card].sample_rate=23.04e6;
	openair0_cfg[card].samples_per_frame = 230400; 
	openair0_cfg[card].tx_bw = 10e6;
	openair0_cfg[card].rx_bw = 10e6;
      }
      else {
	openair0_cfg[card].sample_rate=30.72e6;
	openair0_cfg[card].samples_per_frame = 307200; 
	openair0_cfg[card].tx_bw = 10e6;
	openair0_cfg[card].rx_bw = 10e6;
      }
2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002
    } else if(frame_parms[0]->N_RB_DL == 50) {
      openair0_cfg[card].sample_rate=15.36e6;
      openair0_cfg[card].samples_per_frame = 153600;
      openair0_cfg[card].tx_bw = 5e6;
      openair0_cfg[card].rx_bw = 5e6;
    } else if (frame_parms[0]->N_RB_DL == 25) {
      openair0_cfg[card].sample_rate=7.68e6;
      openair0_cfg[card].samples_per_frame = 76800;
      openair0_cfg[card].tx_bw = 2.5e6;
      openair0_cfg[card].rx_bw = 2.5e6;
    } else if (frame_parms[0]->N_RB_DL == 6) {
      openair0_cfg[card].sample_rate=1.92e6;
      openair0_cfg[card].samples_per_frame = 19200;
      openair0_cfg[card].tx_bw = 1.5e6;
      openair0_cfg[card].rx_bw = 1.5e6;
    }
3003 3004 3005 3006 3007 3008

    if (frame_parms[0]->frame_type==TDD)
      openair0_cfg[card].duplex_mode = duplex_mode_TDD;
    else //FDD
      openair0_cfg[card].duplex_mode = duplex_mode_FDD;

Raymond Knopp's avatar
 
Raymond Knopp committed
3009

3010 3011 3012 3013 3014 3015
    if (local_remote_radio == BBU_REMOTE_RADIO_HEAD) {      
      openair0_cfg[card].remote_addr    = eth_params->remote_addr;
      openair0_cfg[card].remote_port    = eth_params->remote_port;
      openair0_cfg[card].my_addr        = eth_params->my_addr;
      openair0_cfg[card].my_port        = eth_params->my_port;    
    }
3016

3017
    printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card,
3018 3019
           ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->lte_frame_parms.nb_antennas_tx),
           ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx : PHY_vars_UE_g[0][0]->lte_frame_parms.nb_antennas_rx));
Raymond Knopp's avatar
 
Raymond Knopp committed
3020 3021
    openair0_cfg[card].Mod_id = 0;
#ifdef ETHERNET
3022 3023

    if (UE_flag) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3024
      printf("ETHERNET: Configuring UE ETH for %s:%d\n",rrh_UE_ip,rrh_UE_port);
3025
      openair0_cfg[card].remote_addr   = &rrh_UE_ip[0];
3026
      openair0_cfg[card].remote_port = rrh_UE_port;
3027 3028
    } 

3029
    openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL;
Raymond Knopp's avatar
 
Raymond Knopp committed
3030
#endif
3031

3032
    // in the case of the USRP, the following variables need to be initialized before the init
3033
    // since the USRP only supports one CC (for the moment), we initialize all the cards with first CC.
3034
    // in the case of EXMIMO2, these values are overwirtten in the function setup_eNB/UE_buffer
3035
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3036 3037
    openair0_cfg[card].tx_num_channels=min(2,((UE_flag==0) ? PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->lte_frame_parms.nb_antennas_tx));
    openair0_cfg[card].rx_num_channels=min(2,((UE_flag==0) ? PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx : PHY_vars_UE_g[0][0]->lte_frame_parms.nb_antennas_rx));
3038 3039

    for (i=0; i<4; i++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3040

3041 3042 3043 3044 3045 3046 3047 3048
      openair0_cfg[card].tx_freq[i] = (UE_flag==0) ? downlink_frequency[0][i] : downlink_frequency[0][i]+uplink_frequency_offset[0][i];
      openair0_cfg[card].rx_freq[i] = (UE_flag==0) ? downlink_frequency[0][i] + uplink_frequency_offset[0][i] : downlink_frequency[0][i];
      printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n",
             card,i, openair0_cfg[card].tx_gain[i],
             openair0_cfg[card].rx_gain[i],
             openair0_cfg[card].tx_freq[i],
             openair0_cfg[card].rx_freq[i]);
      
3049
      openair0_cfg[card].autocal[i] = 1;
3050
      openair0_cfg[card].tx_gain[i] = tx_gain[0][i];
3051 3052 3053 3054
      if (UE_flag == 0) {
	openair0_cfg[card].rx_gain[i] = PHY_vars_eNB_g[0][0]->rx_total_gain_eNB_dB;
      }
      else {
3055
	openair0_cfg[card].rx_gain[i] = PHY_vars_UE_g[0][0]->rx_total_gain_dB;
3056
      }
3057

3058
#if 0  // UHD 3.8     
3059 3060
      switch(frame_parms[0]->N_RB_DL) {
      case 6:
3061
        openair0_cfg[card].rx_gain[i] -= 12;
3062 3063
        break;

3064
      case 25:
3065
        openair0_cfg[card].rx_gain[i] -= 6;
3066 3067
        break;

3068
      case 50:
3069 3070 3071 3072 3073
        openair0_cfg[card].rx_gain[i] -= 3;
        break;

      case 100:
        openair0_cfg[card].rx_gain[i] -= 0;
3074 3075
        break;

3076
      default:
3077
        break;
3078
      }
3079
#endif      
3080

Raymond Knopp's avatar
 
Raymond Knopp committed
3081
    }
3082

3083
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3084
  }
3085 3086 3087 3088 3089 3090
  /* device host type is set*/
  openair0.host_type = BBU_HOST;
  /* device type is initialized NONE_DEV (no RF device) when the RF device will be initiated device type will be set */
  openair0.type = NONE_DEV;
  /* transport type is initialized NONE_TP (no transport protocol) when the transport protocol will be initiated transport protocol type will be set */
  openair0.transp_type = NONE_TP;
navid's avatar
navid committed
3091
  openair0_cfg[0].log_level = glog_level;
3092

3093 3094 3095 3096 3097 3098 3099 3100 3101 3102
  int returns=-1;
  /* BBU can have either a local or a remote radio head */  
  if (local_remote_radio == BBU_LOCAL_RADIO_HEAD) { //local radio head active  - load library of radio head and initiate it
    if (mode!=loop_through_memory) {
      returns=openair0_device_load(&openair0, &openair0_cfg[0]);
      printf("openair0_device_init returns %d\n",returns);
      if (returns<0) {
	printf("Exiting, cannot initialize device\n");
	exit(-1);
      }
3103
    }
3104 3105 3106 3107 3108 3109 3110 3111 3112 3113
    else if (mode==loop_through_memory) {    
    }
  }  else { //remote radio head active - load library of transport protocol and initiate it 
    if (mode!=loop_through_memory) {
      returns=openair0_transport_load(&openair0, &openair0_cfg[0], eth_params);
      printf("openair0_transport_init returns %d\n",returns);
      if (returns<0) { 
	printf("Exiting, cannot initialize transport protocol\n");
	exit(-1);
      }
3114 3115 3116 3117
    }
    else if (mode==loop_through_memory) {    
    }
  }   
3118
  
3119
  printf("Done\n");
3120 3121 3122

  mac_xface = malloc(sizeof(MAC_xface));

3123
#ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
3124
  int eMBMS_active=0;
3125

Raymond Knopp's avatar
 
Raymond Knopp committed
3126
  l2_init(frame_parms[0],eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL,
3127 3128 3129 3130
          0,// cba_group_active
          0); // HO flag


3131 3132
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3133
  mac_xface->macphy_exit = &exit_fun;
3134

winckel's avatar
winckel committed
3135
#if defined(ENABLE_ITTI)
3136

Raymond Knopp's avatar
 
Raymond Knopp committed
3137
  if (create_tasks(UE_flag ? 0 : 1, UE_flag ? 1 : 0) < 0) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3138
    printf("cannot create ITTI tasks\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3139 3140
    exit(-1); // need a softer mode
  }
3141

Raymond Knopp's avatar
 
Raymond Knopp committed
3142
  printf("ITTI tasks created\n");
winckel's avatar
winckel committed
3143
#endif
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3144 3145

#ifdef OPENAIR2
3146
  if (UE_flag==1) {
3147
    printf("Filling UE band info\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3148
    fill_ue_band_info();
3149
    mac_xface->dl_phy_sync_success (0, 0, 0, 1);
3150
  } else
3151
    mac_xface->mrbch_phy_sync_failure (0, 0, 0);
3152

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3153
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3154

3155
  /* #ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
3156 3157 3158 3159 3160 3161
  //if (otg_enabled) {
  init_all_otg(0);
  g_otg->seed = 0;
  init_seeds(g_otg->seed);
  g_otg->num_nodes = 2;
  for (i=0; i<g_otg->num_nodes; i++){
Raymond Knopp's avatar
 
Raymond Knopp committed
3162 3163 3164 3165 3166 3167
  for (j=0; j<g_otg->num_nodes; j++){
  g_otg->application_idx[i][j] = 1;
  //g_otg->packet_gen_type=SUBSTRACT_STRING;
  g_otg->aggregation_level[i][j][0]=1;
  g_otg->application_type[i][j][0] = BCBR; //MCBR, BCBR
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
3168 3169 3170
  }
  init_predef_traffic(UE_flag ? 1 : 0, UE_flag ? 0 : 1);
  //  }
3171
  #endif */
Raymond Knopp's avatar
 
Raymond Knopp committed
3172

3173
#ifdef EXMIMO
3174
  number_of_cards = openair0_num_detected_cards;
3175 3176
#else
  number_of_cards = 1;
3177
#endif
3178

3179

3180

3181
  for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3182
    rf_map[CC_id].card=0;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3183
    rf_map[CC_id].chain=CC_id+chain_offset;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3184
  }
3185

Raymond Knopp's avatar
 
Raymond Knopp committed
3186 3187
  // connect the TX/RX buffers
  if (UE_flag==1) {
3188
#ifdef OAI_USRP
3189
    openair_daq_vars.timing_advance = timing_advance;
3190
#else
3191
    openair_daq_vars.timing_advance = 160;
3192
#endif
3193
    if (setup_ue_buffers(UE,&openair0_cfg[0],rf_map)!=0) {
3194 3195 3196
      printf("Error setting up eNB buffer\n");
      exit(-1);
    }
3197

3198
    printf("Setting UE buffer to all-RX\n");
3199

3200
    // Set LSBs for antenna switch (ExpressMIMO)
3201
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3202
      for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++)
3203 3204
        for (aa=0; aa<frame_parms[CC_id]->nb_antennas_tx; aa++)
          UE[CC_id]->lte_ue_common_vars.txdata[aa][i] = 0x00010001;
Raymond Knopp's avatar
 
Raymond Knopp committed
3205
    }
3206

3207 3208 3209 3210 3211 3212 3213
    if (input_fd) {
      printf("Reading in from file to antenna buffer %d\n",0);
      fread(UE[0]->lte_ue_common_vars.rxdata[0],
	    sizeof(int32_t),
	    frame_parms[0]->samples_per_tti*10,
	    input_fd);
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3214
    //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX;
3215
  } else {
3216
    openair_daq_vars.timing_advance = 0;
3217

3218 3219 3220 3221
    if (setup_eNB_buffers(PHY_vars_eNB_g[0],&openair0_cfg[0],rf_map)!=0) {
      printf("Error setting up eNB buffer\n");
      exit(-1);
    }
3222

3223
    printf("Setting eNB buffer to all-RX\n");
3224

3225
    // Set LSBs for antenna switch (ExpressMIMO)
3226
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3227
      for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++)
3228 3229
        for (aa=0; aa<frame_parms[CC_id]->nb_antennas_tx; aa++)
          PHY_vars_eNB_g[0][CC_id]->lte_eNB_common_vars.txdata[0][aa][i] = 0x00010001;
Raymond Knopp's avatar
 
Raymond Knopp committed
3230
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3231
  }
3232

3233
#ifdef EXMIMO
3234
  openair0_config(&openair0_cfg[0],UE_flag);
Raymond Knopp's avatar
 
Raymond Knopp committed
3235 3236
#endif

3237
  /*
Raymond Knopp's avatar
 
Raymond Knopp committed
3238 3239
      for (ant=0;ant<4;ant++)
      p_exmimo_config->rf.do_autocal[ant] = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3240
  */
3241 3242

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3243
  error_code = rtf_create(CHANSOUNDER_FIFO_MINOR,CHANSOUNDER_FIFO_SIZE);
3244

Raymond Knopp's avatar
 
Raymond Knopp committed
3245 3246 3247 3248 3249 3250
  if (error_code==0)
    printf("[OPENAIR][SCHED][INIT] Created EMOS FIFO %d\n",CHANSOUNDER_FIFO_MINOR);
  else if (error_code==ENODEV)
    printf("[OPENAIR][SCHED][INIT] Problem: EMOS FIFO %d is greater than or equal to RTF_NO\n",CHANSOUNDER_FIFO_MINOR);
  else if (error_code==ENOMEM)
    printf("[OPENAIR][SCHED][INIT] Problem: cannot allocate memory for EMOS FIFO %d\n",CHANSOUNDER_FIFO_MINOR);
3251
  else
Raymond Knopp's avatar
 
Raymond Knopp committed
3252
    printf("[OPENAIR][SCHED][INIT] Problem creating EMOS FIFO %d, error_code %d\n",CHANSOUNDER_FIFO_MINOR,error_code);
3253

3254 3255
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3256
  mlockall(MCL_CURRENT | MCL_FUTURE);
3257 3258

#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3259
  // make main thread LXRT soft realtime
3260
  /* task = */ rt_task_init_schmod(nam2num("MAIN"), 9, 0, 0, SCHED_FIFO, 0xF);
Raymond Knopp's avatar
 
Raymond Knopp committed
3261 3262 3263 3264 3265

  // start realtime timer and scheduler
  //rt_set_oneshot_mode();
  rt_set_periodic_mode();
  start_rt_timer(0);
3266
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3267

Raymond Knopp's avatar
 
Raymond Knopp committed
3268 3269
  pthread_cond_init(&sync_cond,NULL);
  pthread_mutex_init(&sync_mutex, NULL);
3270

3271
  /*  this is moved to the eNB main thread */ 
3272

3273
//#if defined(ENABLE_ITTI)
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3274
  // Wait for eNB application initialization to be complete (eNB registration to MME)
3275 3276 3277 3278 3279
  //  if (UE_flag==0) {
  // printf("Waiting for eNB application to be ready\n");
    //wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB);
  // }
  //#endif
3280

Raymond Knopp's avatar
 
Raymond Knopp committed
3281 3282

  // this starts the DMA transfers
3283
#ifdef EXMIMO
3284

Raymond Knopp's avatar
 
Raymond Knopp committed
3285
  if (UE_flag!=1)
3286
    for (card=0; card<openair0_num_detected_cards; card++)
3287
      openair0_start_rt_acquisition(card);
3288

Raymond Knopp's avatar
 
Raymond Knopp committed
3289
#endif
3290 3291

#ifdef XFORMS
3292 3293
  int UE_id;

Raymond Knopp's avatar
 
Raymond Knopp committed
3294 3295
  if (do_forms==1) {
    fl_initialize (&argc, argv, NULL, 0, 0);
3296 3297

    if (UE_flag==0) {
3298
      form_stats_l2 = create_form_stats_form();
3299 3300 3301
      fl_show_form (form_stats_l2->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "l2 stats");
      form_stats = create_form_stats_form();
      fl_show_form (form_stats->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "stats");
3302 3303

      for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316
	for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
	  form_enb[CC_id][UE_id] = create_lte_phy_scope_enb();
	  sprintf (title, "LTE UL SCOPE eNB for CC_id %d, UE %d",CC_id,UE_id);
	  fl_show_form (form_enb[CC_id][UE_id]->lte_phy_scope_enb, FL_PLACE_HOTSPOT, FL_FULLBORDER, title);

	  if (otg_enabled) {
	    fl_set_button(form_enb[CC_id][UE_id]->button_0,1);
	    fl_set_object_label(form_enb[CC_id][UE_id]->button_0,"DL Traffic ON");
	  } else {
	    fl_set_button(form_enb[CC_id][UE_id]->button_0,0);
	    fl_set_object_label(form_enb[CC_id][UE_id]->button_0,"DL Traffic OFF");
	  }
	}
3317
      }
3318
    } else {
3319 3320 3321 3322 3323 3324 3325
      form_stats = create_form_stats_form();
      fl_show_form (form_stats->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "stats");
      UE_id = 0;
      form_ue[UE_id] = create_lte_phy_scope_ue();
      sprintf (title, "LTE DL SCOPE UE");
      fl_show_form (form_ue[UE_id]->lte_phy_scope_ue, FL_PLACE_HOTSPOT, FL_FULLBORDER, title);

Raymond Knopp's avatar
 
Raymond Knopp committed
3326
      if (openair_daq_vars.use_ia_receiver) {
3327 3328 3329 3330 3331
        fl_set_button(form_ue[UE_id]->button_0,1);
        fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver ON");
      } else {
        fl_set_button(form_ue[UE_id]->button_0,0);
        fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver OFF");
Raymond Knopp's avatar
 
Raymond Knopp committed
3332 3333 3334
      }
    }

Raymond Knopp's avatar
 
Raymond Knopp committed
3335
    ret = pthread_create(&forms_thread, NULL, scope_thread, NULL);
3336

3337 3338
    if (ret == 0)
      pthread_setname_np( forms_thread, "xforms" );
3339

Raymond Knopp's avatar
 
Raymond Knopp committed
3340 3341
    printf("Scope thread created, ret=%d\n",ret);
  }
3342

3343 3344 3345
#endif

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3346 3347
  ret = pthread_create(&thread3, NULL, emos_thread, NULL);
  printf("EMOS thread created, ret=%d\n",ret);
jiangx's avatar
jiangx committed
3348 3349
  ret = pthread_create(&thread4, NULL, gps_thread, NULL);
  printf("GPS thread created, ret=%d\n",ret);
3350 3351
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3352
  rt_sleep_ns(10*FRAME_PERIOD);
3353 3354

#ifndef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3355
  pthread_attr_init (&attr_dlsch_threads);
3356
  pthread_attr_setstacksize(&attr_dlsch_threads,4*PTHREAD_STACK_MIN);
3357

3358
  pthread_attr_init (&attr_UE_thread);
3359
  pthread_attr_setstacksize(&attr_UE_thread,8192);//5*PTHREAD_STACK_MIN);
3360

3361
#ifndef LOWLATENCY
3362 3363
  sched_param_UE_thread.sched_priority = sched_get_priority_max(SCHED_FIFO);
  pthread_attr_setschedparam(&attr_UE_thread,&sched_param_UE_thread);
3364
  sched_param_dlsch.sched_priority = sched_get_priority_max(SCHED_FIFO); //OPENAIR_THREAD_PRIORITY;
Raymond Knopp's avatar
 
Raymond Knopp committed
3365 3366
  pthread_attr_setschedparam  (&attr_dlsch_threads, &sched_param_dlsch);
  pthread_attr_setschedpolicy (&attr_dlsch_threads, SCHED_FIFO);
3367
  printf("Setting eNB_thread FIFO scheduling policy with priority %d \n", sched_param_dlsch.sched_priority);
3368
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3369

3370 3371
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3372 3373
  // start the main thread
  if (UE_flag == 1) {
3374
    printf("Intializing UE Threads ...\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3375
    init_UE_threads();
3376 3377 3378 3379 3380
#ifdef DLSCH_THREAD
    init_rx_pdsch_thread();
    rt_sleep_ns(FRAME_PERIOD/10);
    init_dlsch_threads();
#endif
3381

3382
    sleep(1);
3383
#ifdef RTAI
3384
    main_ue_thread = rt_thread_create(UE_thread, NULL, 100000000);
3385
#else
3386
    error_code = pthread_create(&main_ue_thread, &attr_UE_thread, UE_thread, NULL);
3387

Raymond Knopp's avatar
 
Raymond Knopp committed
3388 3389 3390
    if (error_code!= 0) {
      LOG_D(HW,"[lte-softmodem.c] Could not allocate UE_thread, error %d\n",error_code);
      return(error_code);
3391
    } else {
3392 3393
      LOG_D( HW, "[lte-softmodem.c] Allocate UE_thread successful\n" );
      pthread_setname_np( main_ue_thread, "main UE" );
Raymond Knopp's avatar
 
Raymond Knopp committed
3394
    }
3395

3396
#endif
3397
    printf("UE threads created\n");
3398 3399 3400 3401 3402 3403 3404 3405 3406 3407
#ifdef USE_MME

    while (start_UE == 0) {
      sleep(1);
    }

#endif



3408
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
3409 3410
    if (multi_thread>0) {
      init_eNB_proc();
3411
      sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3412 3413
      LOG_D(HW,"[lte-softmodem.c] eNB threads created\n");
    }
3414

3415
    printf("Creating main eNB_thread \n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3416
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3417
    main_eNB_thread = rt_thread_create(eNB_thread, NULL, PTHREAD_STACK_MIN);
Raymond Knopp's avatar
 
Raymond Knopp committed
3418
#else
3419
    error_code = pthread_create( &main_eNB_thread, &attr_dlsch_threads, eNB_thread, NULL );
3420

Raymond Knopp's avatar
 
Raymond Knopp committed
3421 3422 3423
    if (error_code!= 0) {
      LOG_D(HW,"[lte-softmodem.c] Could not allocate eNB_thread, error %d\n",error_code);
      return(error_code);
3424
    } else {
3425 3426
      LOG_D( HW, "[lte-softmodem.c] Allocate eNB_thread successful\n" );
      pthread_setname_np( main_eNB_thread, "main eNB" );
Raymond Knopp's avatar
 
Raymond Knopp committed
3427
    }
3428

Raymond Knopp's avatar
 
Raymond Knopp committed
3429 3430
#endif
  }
3431

Raymond Knopp's avatar
 
Raymond Knopp committed
3432
  // Sleep to allow all threads to setup
Raymond Knopp's avatar
 
Raymond Knopp committed
3433
  sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3434

3435

3436

3437
#ifndef EXMIMO
3438

Raymond Knopp's avatar
 
Raymond Knopp committed
3439
#ifndef USRP_DEBUG
3440
  if (mode!=loop_through_memory)
navid's avatar
navid committed
3441 3442 3443
    if (openair0.trx_start_func(&openair0) != 0 ) 
      LOG_E(HW,"Could not start the device\n");

Raymond Knopp's avatar
 
Raymond Knopp committed
3444
#endif
3445

3446 3447
#endif

3448
  printf("Sending sync to all threads\n");
3449

Raymond Knopp's avatar
 
Raymond Knopp committed
3450
  pthread_mutex_lock(&sync_mutex);
3451
  sync_var=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3452 3453
  pthread_cond_broadcast(&sync_cond);
  pthread_mutex_unlock(&sync_mutex);
3454

Raymond Knopp's avatar
 
Raymond Knopp committed
3455 3456 3457
  // wait for end of program
  printf("TYPE <CTRL-C> TO TERMINATE\n");
  //getchar();
3458 3459

#if defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
3460 3461
  printf("Entering ITTI signals handler\n");
  itti_wait_tasks_end();
3462
  oai_exit=1;
3463
#else
3464

Raymond Knopp's avatar
 
Raymond Knopp committed
3465 3466
  while (oai_exit==0)
    rt_sleep_ns(FRAME_PERIOD);
3467

3468
#endif
3469

Raymond Knopp's avatar
 
Raymond Knopp committed
3470
  // stop threads
3471
#ifdef XFORMS
Raymond Knopp's avatar
 
Raymond Knopp committed
3472
  printf("waiting for XFORMS thread\n");
3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486

  if (do_forms==1) {
    pthread_join(forms_thread,&status);
    fl_hide_form(form_stats->stats_form);
    fl_free_form(form_stats->stats_form);

    if (UE_flag==1) {
      fl_hide_form(form_ue[0]->lte_phy_scope_ue);
      fl_free_form(form_ue[0]->lte_phy_scope_ue);
    } else {
      fl_hide_form(form_stats_l2->stats_form);
      fl_free_form(form_stats_l2->stats_form);

      for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
3487 3488 3489 3490
	for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
	  fl_hide_form(form_enb[CC_id][UE_id]->lte_phy_scope_enb);
	  fl_free_form(form_enb[CC_id][UE_id]->lte_phy_scope_enb);
	}
Raymond Knopp's avatar
 
Raymond Knopp committed
3491
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
3492
    }
3493 3494
  }

3495 3496
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3497
  printf("stopping MODEM threads\n");
3498

Raymond Knopp's avatar
 
Raymond Knopp committed
3499 3500
  // cleanup
  if (UE_flag == 1) {
3501
#ifdef EXMIMO
3502
#ifdef RTAI
3503
    rt_thread_join(main_ue_thread);
3504
#else
3505
    pthread_join(main_ue_thread,&status);
3506 3507
#endif
#ifdef DLSCH_THREAD
Raymond Knopp's avatar
 
Raymond Knopp committed
3508 3509
    cleanup_dlsch_threads();
    cleanup_rx_pdsch_thread();
3510
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3511
#endif
3512
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
3513
#ifdef DEBUG_THREADS
Raymond Knopp's avatar
 
Raymond Knopp committed
3514
    printf("Joining eNB_thread ...");
Raymond Knopp's avatar
 
Raymond Knopp committed
3515
#endif
3516
#ifdef RTAI
3517
    rt_thread_join(main_eNB_thread);
3518
#else
3519 3520
    int *eNB_thread_status_p;
    int result = pthread_join( main_eNB_thread, (void**)&eNB_thread_status_p );
Raymond Knopp's avatar
 
Raymond Knopp committed
3521
#ifdef DEBUG_THREADS
3522

3523
    if (result != 0) {
3524
      printf( "\nError joining main_eNB_thread.\n" );
3525
    } else {
3526 3527 3528 3529 3530
      if (eNB_thread_status_p) {
        printf( "status %d\n", *eNB_thread_status_p );
      } else {
        printf( "The thread was killed. No status available.\n");
      }
3531
    }
3532

3533 3534
#else
    UNUSED(result);
3535 3536
#endif // DEBUG_THREADS
#endif // RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3537

Raymond Knopp's avatar
 
Raymond Knopp committed
3538 3539 3540
    if (multi_thread>0) {
      printf("Killing eNB processing threads\n");
      kill_eNB_proc();
Raymond Knopp's avatar
 
Raymond Knopp committed
3541
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3542
  }
3543

3544
#ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
3545
  //cleanup_pdcp_thread();
3546 3547
#endif

3548
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3549
  stop_rt_timer();
3550
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3551 3552
  pthread_cond_destroy(&sync_cond);
  pthread_mutex_destroy(&sync_mutex);
3553

3554

3555
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3556
  printf("stopping card\n");
3557
  openair0_stop(0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3558 3559
  printf("closing openair0_lib\n");
  openair0_close();
navid's avatar
navid committed
3560 3561
#else
  openair0.trx_end_func(&openair0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3562
#endif
3563 3564

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3565 3566 3567
  printf("waiting for EMOS thread\n");
  pthread_cancel(thread3);
  pthread_join(thread3,&status);
jiangx's avatar
jiangx committed
3568 3569 3570
  printf("waiting for GPS thread\n");
  pthread_cancel(thread4);
  pthread_join(thread4,&status);
3571 3572 3573
#endif

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3574 3575
  error_code = rtf_destroy(CHANSOUNDER_FIFO_MINOR);
  printf("[OPENAIR][SCHED][CLEANUP] EMOS FIFO closed, error_code %d\n", error_code);
3576 3577
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3578
  if (ouput_vcd)
3579
    VCD_SIGNAL_DUMPER_CLOSE();
3580

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3581
#ifdef OPENAIR2
3582

3583
  if (opt_enabled == 1)
3584
    terminate_opt();
3585

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3586
#endif
3587

Raymond Knopp's avatar
 
Raymond Knopp committed
3588
  logClean();
3589

Raymond Knopp's avatar
 
Raymond Knopp committed
3590 3591
  return 0;
}
3592 3593


3594 3595 3596
/* this function maps the phy_vars_eNB tx and rx buffers to the available rf chains.
   Each rf chain is is addressed by the card number and the chain on the card. The
   rf_map specifies for each CC, on which rf chain the mapping should start. Multiple
3597
   antennas are mapped to successive RF chains on the same card. */
3598 3599
int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs])
{
3600

3601
  int i, CC_id;
3602
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3603
  uint16_t N_TA_offset = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3604 3605
#else
  int j;
Raymond Knopp's avatar
 
Raymond Knopp committed
3606
#endif
3607
  LTE_DL_FRAME_PARMS *frame_parms;
3608

Raymond Knopp's avatar
 
Raymond Knopp committed
3609

3610 3611
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    if (phy_vars_eNB[CC_id]) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3612 3613
      frame_parms = &(phy_vars_eNB[CC_id]->lte_frame_parms);
      printf("setup_eNB_buffers: frame_parms = %p\n",frame_parms);
3614
    } else {
3615 3616
      printf("phy_vars_eNB[%d] not initialized\n", CC_id);
      return(-1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3617
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3618

3619
#ifndef EXMIMO
3620

3621 3622
    if (frame_parms->frame_type == TDD) {
      if (frame_parms->N_RB_DL == 100)
3623
        N_TA_offset = 624;
3624
      else if (frame_parms->N_RB_DL == 50)
3625
        N_TA_offset = 624/2;
3626
      else if (frame_parms->N_RB_DL == 25)
3627
        N_TA_offset = 624/4;
Raymond Knopp's avatar
 
Raymond Knopp committed
3628
    }
3629

Raymond Knopp's avatar
 
Raymond Knopp committed
3630
#endif
3631

Raymond Knopp's avatar
 
Raymond Knopp committed
3632
    // replace RX signal buffers with mmaped HW versions
3633
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3634 3635 3636
    openair0_cfg[CC_id].tx_num_channels = 0;
    openair0_cfg[CC_id].rx_num_channels = 0;

3637
    for (i=0; i<frame_parms->nb_antennas_rx; i++) {
3638 3639 3640
      printf("Mapping eNB CC_id %d, rx_ant %d, freq %u on card %d, chain %d\n",CC_id,i,downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i],rf_map[CC_id].card,rf_map[CC_id].chain+i);
      free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]);
      phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i] = (int32_t*) openair0_exmimo_pci[rf_map[CC_id].card].adc_head[rf_map[CC_id].chain+i];
3641

3642
      if (openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i]) {
3643 3644 3645 3646 3647 3648
        printf("Error with rf_map! A channel has already been allocated!\n");
        return(-1);
      } else {
        openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i];
        openair0_cfg[rf_map[CC_id].card].rx_gain[rf_map[CC_id].chain+i] = rx_gain[CC_id][i];
        openair0_cfg[rf_map[CC_id].card].rx_num_channels++;
3649
      }
3650

3651
      printf("rxdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]);
3652 3653 3654 3655

      for (j=0; j<16; j++) {
        printf("rxbuffer %d: %x\n",j,phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i][j]);
        phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i][j] = 16-j;
3656
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
3657
    }
3658 3659

    for (i=0; i<frame_parms->nb_antennas_tx; i++) {
3660 3661 3662
      printf("Mapping eNB CC_id %d, tx_ant %d, freq %u on card %d, chain %d\n",CC_id,i,downlink_frequency[CC_id][i],rf_map[CC_id].card,rf_map[CC_id].chain+i);
      free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
      phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i] = (int32_t*) openair0_exmimo_pci[rf_map[CC_id].card].dac_head[rf_map[CC_id].chain+i];
3663

3664
      if (openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i]) {
3665 3666 3667 3668 3669 3670
        printf("Error with rf_map! A channel has already been allocated!\n");
        return(-1);
      } else {
        openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i] = downlink_frequency[CC_id][i];
        openair0_cfg[rf_map[CC_id].card].tx_gain[rf_map[CC_id].chain+i] = tx_gain[CC_id][i];
        openair0_cfg[rf_map[CC_id].card].tx_num_channels++;
3671
      }
3672

3673
      printf("txdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3674 3675 3676 3677

      for (j=0; j<16; j++) {
        printf("txbuffer %d: %x\n",j,phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i][j]);
        phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i][j] = 16-j;
3678
      }
3679
    }
3680

3681
#else // not EXMIMO
3682 3683 3684
    rxdata = (int32_t**)malloc16(frame_parms->nb_antennas_rx*sizeof(int32_t*));
    txdata = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*));

3685
    for (i=0; i<frame_parms->nb_antennas_rx; i++) {
3686
      free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]);
3687
      rxdata[i] = (int32_t*)(32 + malloc16(32+openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation
3688
      phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i] = rxdata[i]-N_TA_offset; // N_TA offset for TDD         FIXME! N_TA_offset > 16 => access of unallocated memory
3689
      memset(rxdata[i], 0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t));
3690
      printf("rxdata[%d] @ %p (%p) (N_TA_OFFSET %d)\n", i, phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i],rxdata[i],N_TA_offset);
3691
      
Raymond Knopp's avatar
 
Raymond Knopp committed
3692
    }
3693 3694

    for (i=0; i<frame_parms->nb_antennas_tx; i++) {
3695
      free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3696
      txdata[i] = (int32_t*)(32 + malloc16(32 + openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation
3697
      phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i] = txdata[i];
3698
      memset(txdata[i],0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t));
3699
      printf("txdata[%d] @ %p\n", i, phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3700

Raymond Knopp's avatar
 
Raymond Knopp committed
3701
    }
3702

Raymond Knopp's avatar
 
Raymond Knopp committed
3703
#endif
3704
  }
3705

3706
  return(0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3707
}
3708

3709
void reset_opp_meas(void) {
3710 3711 3712
  int sfn;
  reset_meas(&softmodem_stats_mt);
  reset_meas(&softmodem_stats_hw);
3713
  
3714 3715 3716 3717 3718 3719
  for (sfn=0; sfn < 10; sfn++) {
    reset_meas(&softmodem_stats_tx_sf[sfn]);
    reset_meas(&softmodem_stats_rx_sf[sfn]);
  }
}

3720 3721
void print_opp_meas(void) {

3722 3723 3724
  int sfn=0;
  print_meas(&softmodem_stats_mt, "Main ENB Thread", NULL, NULL);
  print_meas(&softmodem_stats_hw, "HW Acquisation", NULL, NULL);
3725
  
3726 3727 3728 3729 3730
  for (sfn=0; sfn < 10; sfn++) {
    print_meas(&softmodem_stats_tx_sf[sfn],"[eNB][total_phy_proc_tx]",NULL, NULL);
    print_meas(&softmodem_stats_rx_sf[sfn],"[eNB][total_phy_proc_rx]",NULL,NULL);
  }
}
3731 3732