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

293 294
char   rf_config_file[1024];

Florian Kaltenberger's avatar
Florian Kaltenberger committed
295
int chain_offset=0;
296
int phy_test = 0;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
297

298
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
299 300 301 302
char ref[128] = "internal";
char channels[128] = "0";

#endif
303 304

int                      rx_input_level_dBm;
305
static int                      online_log_messages=0;
306
#ifdef XFORMS
307
extern int                      otg_enabled;
308
static char                     do_forms=0;
309
#else
310
int                             otg_enabled;
311
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
312
//int                             number_of_cards =   1;
Raymond Knopp's avatar
 
Raymond Knopp committed
313
#ifdef EXMIMO
314 315
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
316
#endif
317

Raymond Knopp's avatar
 
Raymond Knopp committed
318
static LTE_DL_FRAME_PARMS      *frame_parms[MAX_NUM_CCs];
319

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

Raymond Knopp's avatar
 
Raymond Knopp committed
327

328
time_stats_t softmodem_stats_mt; // main thread
Raymond Knopp's avatar
 
Raymond Knopp committed
329
time_stats_t softmodem_stats_hw; //  hw acquisition
330 331
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
332 333
void reset_opp_meas(void);
void print_opp_meas(void);
334
int transmission_mode=1;
Raymond Knopp's avatar
 
Raymond Knopp committed
335

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
364 365

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

/* 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
375
char uecap_xer[1024],uecap_xer_in=0;
376 377
extern void *UE_thread(void *arg);
extern void init_UE_threads(void);
Raymond Knopp's avatar
 
Raymond Knopp committed
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 417 418 419
/*---------------------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
}

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

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

429
#if !defined(ENABLE_ITTI)
430 431 432 433 434 435 436 437
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);
438

439 440 441 442
    // print out all the frames to stderr
    fprintf(stderr, "Error: signal %d:\n", sig);
    backtrace_symbols_fd(array, size, 2);
    exit(-1);
443 444
  } else {
    printf("trying to exit gracefully...\n");
445
    oai_exit = 1;
446 447
  }
}
448
#endif
449 450 451 452 453 454 455 456 457 458 459
#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");
460
  printf("  --rf-config-file Configuration file for front-end (e.g. LMS7002M)\n");
461 462 463 464
  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
465 466
  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");
467
  printf("  --no-L2-connect bypass L2 and upper layers\n");
468 469 470 471
  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");
472
  printf("  -C Set the downlink frequency for all component carriers\n");
473 474 475
  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");
476
  printf("  -G Set the global log verbosity \n");
477 478 479 480 481
  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
482
  printf("  -r Set the PRB, valid values: 6, 25, 50, 100  \n");    
483 484
  printf("  -S Skip the missed slots/subframes \n");    
  printf("  -t Set the maximum uplink MCS\n");
485
  printf("  -T Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n");
486 487 488 489
  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);    
490

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

  oai_exit = 1;

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

  //rt_sleep_ns(FRAME_PERIOD);

  //exit (-1);
}

510

511
#ifdef XFORMS
512

513 514
void reset_stats(FL_OBJECT *button, long arg)
{
515 516
  int i,j,k;
  PHY_VARS_eNB *phy_vars_eNB = PHY_vars_eNB_g[0][0];
517 518 519 520 521 522 523

  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;
524
      }
525

526 527 528
      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;
529 530 531 532 533 534

      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;
535
      }
536
    }
537

538 539 540
    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;
541 542 543
  }
}

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

554
  sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
Raymond Knopp's avatar
 
Raymond Knopp committed
555
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
556

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

559
# ifdef ENABLE_XFORMS_WRITE_STATS
560 561

  if (UE_flag==1)
Raymond Knopp's avatar
 
Raymond Knopp committed
562
    UE_stats  = fopen("UE_stats.txt", "w");
563
  else
Raymond Knopp's avatar
 
Raymond Knopp committed
564
    eNB_stats = fopen("eNB_stats.txt", "w");
565

566
#endif
567

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

575 576 577 578 579
      phy_scope_UE(form_ue[0],
                   PHY_vars_UE_g[0][0],
                   0,
                   0,7);

Raymond Knopp's avatar
 
Raymond Knopp committed
580
    } else {
581 582 583 584 585 586
      if (PHY_vars_eNB_g[0][0]->mac_enabled==1) {
	len = dump_eNB_l2_stats (stats_buffer, 0);
	//fl_set_object_label(form_stats_l2->stats_text, stats_buffer);
	fl_clear_browser(form_stats_l2->stats_text);
	fl_add_browser_line(form_stats_l2->stats_text, stats_buffer);
      }
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
587
      len = dump_eNB_stats (PHY_vars_eNB_g[0][0], stats_buffer, 0);
588

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

592 593 594
      //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);
595

596
      for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
597 598 599 600 601
	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
602
      }
603

604
    }
605

Raymond Knopp's avatar
 
Raymond Knopp committed
606
    //printf("doing forms\n");
Florian Kaltenberger's avatar
Florian Kaltenberger committed
607 608
    //usleep(100000); // 100 ms
    sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
609
  }
610

611
  //  printf("%s",stats_buffer);
612

613
# ifdef ENABLE_XFORMS_WRITE_STATS
614

615 616 617 618 619 620
  if (UE_flag==1) {
    if (UE_stats) {
      rewind (UE_stats);
      fwrite (stats_buffer, 1, len, UE_stats);
      fclose (UE_stats);
    }
621
  } else {
622 623 624 625 626 627
    if (eNB_stats) {
      rewind (eNB_stats);
      fwrite (stats_buffer, 1, len, eNB_stats);
      fclose (eNB_stats);
    }
  }
628

629
# endif
630

Raymond Knopp's avatar
 
Raymond Knopp committed
631
  pthread_exit((void*)arg);
632 633 634 635 636 637
}
#endif

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

jiangx's avatar
jiangx committed
638 639 640 641 642 643 644 645
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;

646
  sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
jiangx's avatar
jiangx committed
647
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
648

jiangx's avatar
jiangx committed
649 650 651
  printf("GPS thread has priority %d\n",sched_param.sched_priority);

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

jiangx's avatar
jiangx committed
653 654
#if GPSD_API_MAJOR_VERSION>=5
  ret = gps_open("127.0.0.1","2947",gps_data_ptr);
655

jiangx's avatar
jiangx committed
656 657 658
  if (ret!=0)
#else
  gps_data_ptr = gps_open("127.0.0.1","2947");
659 660

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

jiangx's avatar
jiangx committed
667 668 669 670 671
#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
672 673 674 675
  {
    printf("[EMOS] Error sending command to GPS\n");
    pthread_exit((void*) arg);
  } else
jiangx's avatar
jiangx committed
676 677
    printf("[EMOS] Opened GPS, gps_data=%p\n", gps_data_ptr);

678 679 680

  while (!oai_exit) {
    printf("[EMOS] polling data from gps\n");
jiangx's avatar
jiangx committed
681
#if GPSD_API_MAJOR_VERSION>=5
682 683 684

    if (gps_waiting(gps_data_ptr,500)) {
      if (gps_read(gps_data_ptr) <= 0) {
jiangx's avatar
jiangx committed
685
#else
686 687 688 689 690 691 692 693

    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
694
      }
695 696 697 698 699 700 701 702
    } //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
703 704 705 706 707

  pthread_exit((void*) arg);

}

708 709 710 711 712 713 714 715 716 717 718
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;
719

jiangx's avatar
jiangx committed
720
  int channel_buffer_size,ret;
721

722 723 724
  time_t timer;
  struct tm *now;

725
  struct sched_param sched_param;
726 727

  sched_param.sched_priority = sched_get_priority_max(SCHED_FIFO)-1;
728
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
729

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

732 733 734 735 736 737 738 739 740 741 742 743
  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;

744 745 746 747
  if (fifo2file_buffer == NULL) {
    printf("[EMOS] Cound not allocate memory for fifo2file_buffer\n");
    exit(EXIT_FAILURE);
  }
748

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


  time(&starttime_tmp);
  localtime_r(&starttime_tmp,&starttime);
  snprintf(dumpfile_name,1024,"/tmp/%s_data_%d%02d%02d_%02d%02d%02d.EMOS",
758 759
           (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);
760 761

  dumpfile_id = fopen(dumpfile_name,"w");
762 763 764 765 766

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


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

771 772 773 774 775 776 777
  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);
778

779 780 781 782
    if (bytes<=0) {
      usleep(100);
      continue;
    }
783

784 785 786
    if (bytes != channel_buffer_size) {
      printf("[EMOS] ERROR! Only got %d bytes instead of %d!\n",bytes,channel_buffer_size);
    }
787

788 789 790 791 792 793
    /*
    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);
    */
794

795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815
    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
816

817 818 819 820
      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);
      }
821
    }
822 823
  }

824 825 826
  free(fifo2file_buffer);
  fclose(dumpfile_id);
  close(fifo);
827

828 829 830 831 832
  pthread_exit((void*) arg);

}
#endif

833 834


835
#if defined(ENABLE_ITTI)
836 837 838 839 840
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[] = {".    ", "..   ", "...  ", ".... ", ".....",
841 842
                                " ....", "  ...", "   ..", "    .", "     "
                               };
843 844 845 846
    int i = 0;

    while ((!oai_exit) && (*start_flag == 0)) {
      LOG_N(EMU, message, indicator[i]);
847
      fflush(stdout);
848 849 850
      i = (i + 1) % (sizeof(indicator) / sizeof(indicator[0]));
      usleep(200000);
    }
851

852 853 854 855 856
    LOG_D(EMU,"\n");
  }
}
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
857
#if defined(ENABLE_ITTI)
858
void *l2l1_task(void *arg)
859
{
Raymond Knopp's avatar
 
Raymond Knopp committed
860 861 862 863 864
  MessageDef *message_p = NULL;
  int         result;

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
865

Raymond Knopp's avatar
 
Raymond Knopp committed
866 867
  if (UE_flag == 0) {
    /* Wait for the initialize message */
868
    printf("Wait for the ITTI initialize message\n");
869
    do {
Raymond Knopp's avatar
 
Raymond Knopp committed
870
      if (message_p != NULL) {
871 872
        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
873
      }
874

875 876 877
      itti_receive_msg (TASK_L2L1, &message_p);

      switch (ITTI_MSG_ID(message_p)) {
Raymond Knopp's avatar
 
Raymond Knopp committed
878
      case INITIALIZE_MESSAGE:
879 880 881 882
        /* 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
883 884

      case TERMINATE_MESSAGE:
885 886 887 888
        printf("received terminate message\n");
        oai_exit=1;
        itti_exit_task ();
        break;
Raymond Knopp's avatar
 
Raymond Knopp committed
889 890

      default:
891 892
        LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
        break;
893
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
894
    } while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE);
895

Raymond Knopp's avatar
 
Raymond Knopp committed
896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916
    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;
917

Raymond Knopp's avatar
 
Raymond Knopp committed
918 919 920 921 922 923 924 925 926 927 928
    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);
929
  } while(!oai_exit);
930

Raymond Knopp's avatar
 
Raymond Knopp committed
931
  return NULL;
932 933 934
}
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
935

936 937
void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
938 939 940 941

  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
942
  int slot_sizeF = (phy_vars_eNB->lte_frame_parms.ofdm_symbol_size)*
943
                   ((phy_vars_eNB->lte_frame_parms.Ncp==1) ? 6 : 7);
944
  int len;
Raymond Knopp's avatar
 
Raymond Knopp committed
945 946

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
954

Raymond Knopp's avatar
 
Raymond Knopp committed
955
    for (aa=0; aa<phy_vars_eNB->lte_frame_parms.nb_antennas_tx; aa++) {
956 957 958
      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,
959
                     phy_vars_eNB->lte_frame_parms.ofdm_symbol_size,
960 961 962 963 964
                     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),
965
                     phy_vars_eNB->lte_frame_parms.ofdm_symbol_size,
966 967 968 969 970 971 972 973
                     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));
974 975 976 977 978 979
	// 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
980
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
981

982 983 984 985 986
      // 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;
kaltenbe's avatar
kaltenbe committed
987
      /*
988 989 990 991 992
      for (i=0;i<len;i+=4) {
	dummy_tx_b[i] = 0x100;
	dummy_tx_b[i+1] = 0x01000000;
	dummy_tx_b[i+2] = 0xff00;
	dummy_tx_b[i+3] = 0xff000000;
kaltenbe's avatar
kaltenbe committed
993
	}*/
994
      for (i=0; i<len; i++) {
995 996
        tx_offset = (int)slot_offset+time_offset[aa]+i;

997
	
998 999 1000 1001 1002 1003
        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;

1004 1005 1006
	((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;
1007 1008 1009 1010 1011 1012 1013
     }
     // 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;
       }
     }
1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032

     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
1033 1034 1035 1036
    }
  }
}

1037 1038 1039 1040 1041 1042 1043 1044 1045
/* 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
1046

1047 1048 1049 1050 1051 1052 1053 1054 1055
/*!
 * \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
1056 1057

  eNB_proc_t *proc = (eNB_proc_t*)param;
1058 1059
  FILE  *tx_time_file;
  char tx_time_name[101];
kaltenbe's avatar
kaltenbe committed
1060

1061 1062 1063 1064
  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");
  }
1065 1066 1067
  // set default return value
  eNB_thread_tx_status[proc->subframe] = 0;

1068 1069
  MSC_START_USE();

Raymond Knopp's avatar
 
Raymond Knopp committed
1070 1071
#ifdef RTAI
  RT_TASK *task;
1072
  char task_name[8];
Raymond Knopp's avatar
 
Raymond Knopp committed
1073

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

1077 1078 1079
  if (task == NULL) {
    LOG_E(PHY,"[SCHED][eNB] Problem starting eNB_proc_TX thread_index %d (%s)!!!!\n",proc->subframe,task_name);
    return 0;
1080 1081 1082 1083 1084
  } else {
    LOG_I(PHY,"[SCHED][eNB] eNB TX thread CC %d SF %d started with id %p\n",
          proc->CC_id,
          proc->subframe,
          task);
1085
  }
1086

Raymond Knopp's avatar
 
Raymond Knopp committed
1087
#else
1088
#ifdef LOWLATENCY
1089 1090
  struct sched_attr attr;
  unsigned int flags = 0;
navid's avatar
navid committed
1091 1092 1093 1094 1095 1096 1097
  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; 
  }
1098

1099 1100 1101 1102
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1103

navid's avatar
navid committed
1104 1105 1106 1107
  attr.sched_policy   = SCHED_DEADLINE;
  attr.sched_runtime  = runtime;
  attr.sched_deadline = deadline;
  attr.sched_period   = period; 
1108

1109 1110 1111 1112
  if (sched_setattr(0, &attr, flags) < 0 ) {
    perror("[SCHED] eNB tx thread: sched_setattr failed\n");
    return &eNB_thread_tx_status[proc->subframe];
  }
1113

navid's avatar
navid committed
1114
  LOG_I( HW, "[SCHED] eNB TX deadline thread %d(TID %ld) started on CPU %d\n", proc->subframe, gettid(), sched_getcpu() );
1115
#else
1116
  LOG_I( HW, "[SCHED][eNB] TX thread %d started on CPU %d TID %d\n", proc->subframe, sched_getcpu(),gettid() );
1117 1118
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
1119 1120 1121 1122 1123 1124 1125 1126
#endif

  mlockall(MCL_CURRENT | MCL_FUTURE);

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

1127
  while (!oai_exit) {
1128

1129
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe), 0 );
1130

1131
    if (pthread_mutex_lock(&proc->mutex_tx) != 0) {
1132
      LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc %d\n", proc->subframe );
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1133
      exit_fun("nothing to add");
1134
      break;
1135
    }
1136

1137
    while (proc->instance_cnt_tx < 0) {
1138 1139 1140
      // 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
1141
    }
1142

1143 1144 1145 1146 1147
    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
1148

1149 1150
    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 );
1151 1152 1153
    start_meas( &softmodem_stats_tx_sf[proc->subframe] );

    if (oai_exit) break;
1154

1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166
    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;
      }
1167 1168
      /* wait for our turn or oai_exit */
      while (sync_phy_proc[proc->subframe].phy_proc_CC_id != proc->CC_id && !oai_exit) {
1169 1170 1171
        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
1172

1173 1174 1175
      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");
1176 1177
      }

1178 1179 1180
      if (oai_exit)
        break;

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

1183
      /* we're done, let the next one proceed */
1184 1185 1186 1187 1188
      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;
      }
1189 1190 1191 1192
      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) {
1193
        LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc %d\n", proc->subframe);
1194 1195 1196
        exit_fun("nothing to add");
        break;
      }
1197
    }
1198

1199
    do_OFDM_mod_rt( proc->subframe_tx, PHY_vars_eNB_g[0][proc->CC_id] );
kaltenbe's avatar
kaltenbe committed
1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213
    /*
    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;
    }
    */
1214 1215 1216 1217 1218
    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
1219

1220 1221 1222 1223 1224 1225 1226 1227 1228
    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++;
1229

1230 1231
    if (proc->frame_tx==1024)
      proc->frame_tx=0;
1232
    stop_meas( &softmodem_stats_tx_sf[proc->subframe] );
1233 1234 1235 1236 1237 1238 1239
#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 
1240 1241
    print_meas_now(&softmodem_stats_tx_sf[proc->subframe],"eNB_TX_SF",proc->subframe, tx_time_file);

1242 1243
  }

1244 1245


1246
  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
1247

Raymond Knopp's avatar
 
Raymond Knopp committed
1248 1249 1250
#ifdef HARD_RT
  rt_make_soft_real_time();
#endif
1251

Raymond Knopp's avatar
 
Raymond Knopp committed
1252
#ifdef DEBUG_THREADS
1253
  printf( "Exiting eNB thread TX %d\n", proc->subframe );
Raymond Knopp's avatar
 
Raymond Knopp committed
1254 1255 1256 1257 1258
#endif
  // clean task
#ifdef RTAI
  rt_task_delete(task);
#endif
1259

1260 1261
  eNB_thread_tx_status[proc->subframe] = 0;
  return &eNB_thread_tx_status[proc->subframe];
Raymond Knopp's avatar
 
Raymond Knopp committed
1262 1263 1264
}


1265 1266 1267 1268 1269 1270 1271 1272 1273 1274
/*!
 * \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
1275
  eNB_proc_t *proc = (eNB_proc_t*)param;
1276

1277 1278
  FILE  *rx_time_file;
  char rx_time_name[101];
1279
  //int i;
Raymond Knopp's avatar
 
Raymond Knopp committed
1280

1281 1282 1283 1284
  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");
  }
1285 1286 1287
  // set default return value
  eNB_thread_rx_status[proc->subframe] = 0;

1288 1289
  MSC_START_USE();

Raymond Knopp's avatar
 
Raymond Knopp committed
1290 1291
#ifdef RTAI
  RT_TASK *task;
1292
  char task_name[8];
Raymond Knopp's avatar
 
Raymond Knopp committed
1293

1294
  sprintf(task_name,"RXC%1dS%1d",proc->CC_id,proc->subframe);
Raymond Knopp's avatar
 
Raymond Knopp committed
1295 1296 1297
  task = rt_task_init_schmod(nam2num(task_name), 0, 0, 0, SCHED_FIFO, 0xF);

  if (task==NULL) {
1298 1299
    LOG_E(PHY,"[SCHED][eNB] Problem starting eNB_proc_RX thread_index %d (%s)!!!!\n",proc->subframe,task_name);
    return 0;
1300
  } else {
1301
    LOG_I(PHY,"[SCHED][eNB] eNB RX thread CC_id %d SF %d started with id %p\n", /*  on CPU %d*/
1302 1303 1304
          proc->CC_id,
          proc->subframe,
          task); /*,rtai_cpuid()*/
Raymond Knopp's avatar
 
Raymond Knopp committed
1305
  }
1306

Raymond Knopp's avatar
 
Raymond Knopp committed
1307
#else
1308
#ifdef LOWLATENCY
1309 1310
  struct sched_attr attr;
  unsigned int flags = 0;
navid's avatar
navid committed
1311 1312 1313 1314 1315 1316 1317 1318
  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;
  }
1319

1320 1321 1322 1323
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1324

1325
  attr.sched_policy = SCHED_DEADLINE;
navid's avatar
navid committed
1326 1327 1328
  attr.sched_runtime  = runtime;
  attr.sched_deadline = deadline;
  attr.sched_period   = period; 
1329 1330

  if (sched_setattr(0, &attr, flags) < 0 ) {
1331
    perror("[SCHED] eNB RX sched_setattr failed\n");
1332
    return &eNB_thread_rx_status[proc->subframe];
1333
  }
1334

1335
  LOG_I( HW, "[SCHED] eNB RX deadline thread %d(TID %ld) started on CPU %d\n", proc->subframe, gettid(), sched_getcpu() );
1336
#else
1337
  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
1338
#endif
1339
#endif // RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
1340 1341 1342 1343 1344 1345 1346

  mlockall(MCL_CURRENT | MCL_FUTURE);

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

1347
  while (!oai_exit) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1348

1349
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 0 );
1350

Raymond Knopp's avatar
 
Raymond Knopp committed
1351
    if (pthread_mutex_lock(&proc->mutex_rx) != 0) {
1352 1353 1354
      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
1355 1356
    }

1357
    while (proc->instance_cnt_rx < 0) {
1358 1359 1360
      // 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
1361
    }
1362 1363 1364 1365 1366 1367 1368

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

1369 1370
    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 );
1371
    start_meas( &softmodem_stats_rx_sf[proc->subframe] );
1372

Raymond Knopp's avatar
 
Raymond Knopp committed
1373
    if (oai_exit) break;
1374

Raymond Knopp's avatar
 
Raymond Knopp committed
1375
    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)) ||
1376
         (PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == FDD))) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1377

1378
      phy_procedures_eNB_RX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay );
Raymond Knopp's avatar
 
Raymond Knopp committed
1379
    }
1380 1381

    if ((subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_rx) == SF_S)) {
1382
      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
1383
    }
1384

Raymond Knopp's avatar
 
Raymond Knopp committed
1385
    if (pthread_mutex_lock(&proc->mutex_rx) != 0) {
1386 1387 1388
      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
1389
    }
1390 1391 1392 1393 1394 1395 1396

    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
1397
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1398 1399

    proc->frame_rx++;
1400

Raymond Knopp's avatar
 
Raymond Knopp committed
1401 1402
    if (proc->frame_rx==1024)
      proc->frame_rx=0;
1403

1404
    stop_meas( &softmodem_stats_rx_sf[proc->subframe] );
1405 1406 1407 1408 1409 1410 1411
#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  
1412
    print_meas_now(&softmodem_stats_rx_sf[proc->subframe],"eNB_RX_SF",proc->subframe, rx_time_file);
Raymond Knopp's avatar
 
Raymond Knopp committed
1413
  }
1414

1415
  //stop_meas( &softmodem_stats_rx_sf[proc->subframe] );
1416
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 0 );
1417

Raymond Knopp's avatar
 
Raymond Knopp committed
1418
#ifdef HARD_RT
Raymond Knopp's avatar
 
Raymond Knopp committed
1419 1420 1421 1422
  rt_make_soft_real_time();
#endif

#ifdef DEBUG_THREADS
1423
  printf( "Exiting eNB thread RX %d\n", proc->subframe );
Raymond Knopp's avatar
 
Raymond Knopp committed
1424 1425 1426 1427
#endif
  // clean task
#ifdef RTAI
  rt_task_delete(task);
Raymond Knopp's avatar
 
Raymond Knopp committed
1428 1429
#endif

1430 1431
  eNB_thread_rx_status[proc->subframe] = 0;
  return &eNB_thread_rx_status[proc->subframe];
Raymond Knopp's avatar
 
Raymond Knopp committed
1432 1433 1434 1435
}



Raymond Knopp's avatar
 
Raymond Knopp committed
1436

1437 1438
void init_eNB_proc(void)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1439
  int i;
Raymond Knopp's avatar
 
Raymond Knopp committed
1440 1441
  int CC_id;

1442 1443 1444
  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
1445
     
1446

navid's avatar
navid committed
1447 1448 1449 1450 1451 1452
#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");
      
1453
      pthread_attr_init( &attr_eNB_proc_rx[CC_id][i] );
navid's avatar
navid committed
1454
      if (pthread_attr_setstacksize( &attr_eNB_proc_rx[CC_id][i], 64 * PTHREAD_STACK_MIN ) != 0)
1455
        perror("[ENB_PROC_RX] setting thread stack size failed\n");
1456
      */
1457
      // set the kernel scheduling policy and priority
Raymond Knopp's avatar
 
Raymond Knopp committed
1458 1459 1460 1461 1462 1463
      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);
1464
      printf("Setting OS scheduler to SCHED_FIFO for eNB [cc%d][thread%d] \n",CC_id, i);
1465
#endif
1466 1467 1468
      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
1469
      PHY_vars_eNB_g[0][CC_id]->proc[i].CC_id = CC_id;
1470 1471 1472 1473
      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);
1474 1475 1476 1477
#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 
1478 1479
      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] );
1480
#endif
1481 1482 1483 1484 1485
      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
1486 1487
      PHY_vars_eNB_g[0][CC_id]->proc[i].frame_tx = 0;
      PHY_vars_eNB_g[0][CC_id]->proc[i].frame_rx = 0;
1488
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
1489 1490
      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
1491
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
1492 1493
      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
1494
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1495
    }
1496 1497


1498
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
1499 1500
    // 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
1501

Raymond Knopp's avatar
 
Raymond Knopp committed
1502
    //PHY_vars_eNB_g[0][CC_id]->proc[0].frame_rx = 1023;
Raymond Knopp's avatar
 
Raymond Knopp committed
1503 1504
    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
1505
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
1506 1507
    // 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
1508
    //    PHY_vars_eNB_g[0][CC_id]->proc[7].frame_tx = 1;
Raymond Knopp's avatar
 
Raymond Knopp committed
1509 1510
    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
1511
    //    PHY_vars_eNB_g[0][CC_id]->proc[0].frame_tx = 1;
Raymond Knopp's avatar
 
Raymond Knopp committed
1512
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1513
  }
1514 1515 1516 1517 1518 1519 1520

  /* 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
1521
}
Raymond Knopp's avatar
 
Raymond Knopp committed
1522

1523 1524 1525 1526 1527 1528
/*!
 * \brief Terminate eNB TX and RX threads.
 */
void kill_eNB_proc(void)
{
  int *status;
Raymond Knopp's avatar
 
Raymond Knopp committed
1529

1530 1531
  for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++)
    for (int i=0; i<NUM_ENB_THREADS; i++) {
1532

Raymond Knopp's avatar
 
Raymond Knopp committed
1533
#ifdef DEBUG_THREADS
1534
      printf( "Killing TX CC_id %d thread %d\n", CC_id, i );
Raymond Knopp's avatar
 
Raymond Knopp committed
1535
#endif
1536 1537 1538

      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 );
1539
      pthread_cond_broadcast(&sync_phy_proc[i].cond_phy_proc_tx);
1540

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1546
#ifdef DEBUG_THREADS
1547

1548 1549 1550 1551 1552 1553 1554 1555 1556
      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" );
        }
      }
1557

1558 1559
#else
      UNUSED(result)
Raymond Knopp's avatar
 
Raymond Knopp committed
1560
#endif
1561

Raymond Knopp's avatar
 
Raymond Knopp committed
1562
#ifdef DEBUG_THREADS
1563
      printf( "Killing RX CC_id %d thread %d\n", CC_id, i );
Raymond Knopp's avatar
 
Raymond Knopp committed
1564
#endif
1565 1566 1567 1568

      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
1569
#ifdef DEBUG_THREADS
1570
      printf( "Joining eNB RX CC_id %d thread %d...\n", CC_id, i );
Raymond Knopp's avatar
 
Raymond Knopp committed
1571
#endif
1572 1573
      result = pthread_join( PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_rx, (void**)&status );

1574 1575
#ifdef DEBUG_THREADS

1576 1577 1578 1579 1580 1581 1582 1583 1584
      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" );
        }
      }
1585

1586 1587
#else
      UNUSED(result)
Raymond Knopp's avatar
 
Raymond Knopp committed
1588
#endif
1589 1590 1591 1592 1593

      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
1594
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1595 1596 1597
}


Raymond Knopp's avatar
 
Raymond Knopp committed
1598 1599


1600

Raymond Knopp's avatar
 
Raymond Knopp committed
1601

1602 1603 1604 1605 1606 1607
/*!
 * \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 )
1608
{
1609 1610
  UNUSED(arg);
  static int eNB_thread_status;
1611

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

  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
1632

1633
  int hw_subframe = 0; // 0..NUM_ENB_THREADS-1 => 0..9
1634
  
1635
  unsigned int rx_pos = 0;
1636
  unsigned int tx_pos = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
1637
#endif
1638
  int CC_id=0;	
1639
  struct timespec trx_time0, trx_time1, trx_time2;
1640

1641
#ifdef RTAI
1642
  RT_TASK* task = rt_task_init_schmod(nam2num("eNBmain"), 0, 0, 0, SCHED_FIFO, 0xF);
1643
#else
1644
#ifdef LOWLATENCY
1645 1646 1647
  struct sched_attr attr;
  unsigned int flags = 0;

Raymond Knopp's avatar
 
Raymond Knopp committed
1648 1649 1650 1651
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1652

1653
  /* This creates a .2 ms  reservation */
Raymond Knopp's avatar
 
Raymond Knopp committed
1654
  attr.sched_policy = SCHED_DEADLINE;
navid's avatar
navid committed
1655
  attr.sched_runtime  = (0.3 * 100) * 10000;
1656 1657
  attr.sched_deadline = (0.9 * 100) * 10000;
  attr.sched_period   = 1 * 1000000;
1658

Lionel Gauthier's avatar
Lionel Gauthier committed
1659

Raymond Knopp's avatar
 
Raymond Knopp committed
1660 1661 1662 1663
  /* 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");
     }*/
1664

1665
  if (sched_setattr(0, &attr, flags) < 0 ) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1666 1667 1668 1669
    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",
1670
          gettid(),sched_getcpu());
Raymond Knopp's avatar
 
Raymond Knopp committed
1671
  }
1672

1673
#endif
1674 1675
#endif

1676 1677 1678 1679 1680
  // stop early, if an exit is requested
  // FIXME really neccessary?
  if (oai_exit)
    goto eNB_thread_cleanup;

1681
#ifdef RTAI
1682
  printf( "[SCHED][eNB] Started eNB main thread (id %p)\n", task );
Raymond Knopp's avatar
 
Raymond Knopp committed
1683
#else
1684
  printf( "[SCHED][eNB] Started eNB main thread on CPU %d TID %d\n", sched_getcpu(), gettid());
1685 1686 1687
#endif

#ifdef HARD_RT
1688
  rt_make_hard_real_time();
1689 1690
#endif

1691 1692 1693 1694 1695 1696 1697 1698
  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;
1699

1700 1701
  printf( "waiting for sync (eNB_thread)\n" );
  pthread_mutex_lock( &sync_mutex );
1702

1703 1704
  while (sync_var<0)
    pthread_cond_wait( &sync_cond, &sync_mutex );
1705

1706
  pthread_mutex_unlock(&sync_mutex);
1707

1708 1709
  printf( "got sync (eNB_thread)\n" );

1710
  int frame = 0;
1711

1712
#ifndef EXMIMO
1713 1714
  spp        = openair0_cfg[0].samples_per_packet;
  tx_pos     = openair0_cfg[0].tx_scheduling_advance;
1715
#endif
1716

1717 1718 1719 1720
#if defined(ENABLE_ITTI)
  wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB);
#endif 

1721 1722
  while (!oai_exit) {
    start_meas( &softmodem_stats_mt );
Raymond Knopp's avatar
 
Raymond Knopp committed
1723

1724
#ifdef EXMIMO
1725 1726
    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]);
1727 1728
    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);
1729 1730 1731 1732
    //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];
1733

1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744
    //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;
1745

1746
      if (diff<0)
1747
        diff = diff + 150;
1748

1749 1750 1751 1752
      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)))) {
1753

1754 1755 1756 1757
      // 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);
      
1758
      if (exit_missed_slots==1) {
1759 1760
        stop_meas(&softmodem_stats_mt);
        exit_fun("[HW][eNB] missed slot");
1761
      } else {
1762
        num_missed_slots++;
1763
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_MISSED_SLOTS_ENB,num_missed_slots );
1764
      }
1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786

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

    
1787
    }
1788

1789
    if (diff>8)
1790 1791
      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);
1792

1793 1794
    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);
1795 1796

    delay_cnt = 0;
1797

1798 1799 1800 1801
    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);
1802
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP,1);
1803
      ret = rt_sleep_ns(diff*DAQ_PERIOD);
1804 1805
      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);
1806

1807 1808
      if (ret)
        LOG_D(HW,"eNB Frame %d, time %llu: rt_sleep_ns returned %d\n",frame, time_in);
1809

Raymond Knopp's avatar
 
Raymond Knopp committed
1810
      hw_slot = (((((volatile unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15;
1811 1812 1813
      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());
1814
      delay_cnt++;
1815

1816 1817 1818 1819 1820
      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");
      }
1821

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1824
      if ((mbox_current>=135) && (mbox_target<15)) //handle the frame wrap-arround
1825
        diff = 150-mbox_current+mbox_target;
Raymond Knopp's avatar
 
Raymond Knopp committed
1826
      else if ((mbox_current<15) && (mbox_target>=135))
1827
        diff = -150+mbox_target-mbox_current;
Raymond Knopp's avatar
 
Raymond Knopp committed
1828
      else
1829 1830
        diff = mbox_target - mbox_current;
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1831

1832
#else  // EXMIMO
1833 1834
    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 );
1835
    tx_launched = 0;
1836

1837
    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
1838

1839
      unsigned int rxs;
Raymond Knopp's avatar
 
Raymond Knopp committed
1840
#ifndef USRP_DEBUG
1841 1842 1843
      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
1844

1845
      clock_gettime( CLOCK_MONOTONIC, &trx_time0 );
1846

1847
       start_meas( &softmodem_stats_hw );
1848

1849
      openair0_timestamp timestamp;
1850 1851
      int i=0;
      // prepare rx buffer pointers
1852
      for (i=0; i<PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx; i++)
1853 1854 1855 1856 1857 1858 1859
        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,
1860 1861
				     PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx);
      
1862
      stop_meas( &softmodem_stats_hw );
1863 1864 1865
      if (frame > 50) { 
	  clock_gettime( CLOCK_MONOTONIC, &trx_time1 );
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
1866

navid's avatar
navid committed
1867
      if (frame > 20){ 
1868 1869 1870
	if (rxs != spp)
	  exit_fun( "problem receiving samples" );
      }
1871
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
1872

1873
      // Transmit TX buffer based on timestamp from RX
1874 1875 1876 1877 1878 1879
    
      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
1880
      if (frame > 50) {
1881
	openair0.trx_write_func(&openair0,
1882
				(timestamp+(openair0_cfg[card].tx_scheduling_advance)-openair0_cfg[card].tx_sample_advance),
1883 1884 1885 1886
				txp,
				spp,
				PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx,
				1);
navid's avatar
navid committed
1887 1888
      }
      
1889
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, timestamp&0xffffffff );
1890
      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 );
1891 1892

      stop_meas( &softmodem_stats_mt );
1893 1894
      if (frame > 50) { 
	  clock_gettime( CLOCK_MONOTONIC, &trx_time2 );
Aikaterini's avatar
Aikaterini committed
1895
	  //update_difftimes(trx_time1, trx_time2);
1896 1897
      }

1898

1899
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE,0);
1900 1901 1902 1903
#else
      // USRP_DEBUG is active
      rt_sleep_ns(1000000);
#endif
1904 1905 1906 1907 1908 1909
      /* 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
1910
      if ( (frame>50) && (tx_launched == 0) &&
1911 1912
	   ((openair0_cfg[card].txlaunch_wait == 0) ||
	    ((openair0_cfg[card].txlaunch_wait == 1) &&
1913
	     (rx_pos >= (((2*hw_subframe)+openair0_cfg[card].txlaunch_wait_slotcount)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))))) { 
1914
	
1915
        tx_launched = 1;
1916

1917
        for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945
          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;

1946 1947
      if (tx_pos >= openair0_cfg[card].samples_per_frame)
        tx_pos -= openair0_cfg[card].samples_per_frame;
1948 1949
    }

1950 1951
    if (rx_pos >= openair0_cfg[card].samples_per_frame)
      rx_pos -= openair0_cfg[card].samples_per_frame;
1952

Raymond Knopp's avatar
 
Raymond Knopp committed
1953 1954

#endif // USRP
1955

1956
    if (oai_exit) break;
Raymond Knopp's avatar
 
Raymond Knopp committed
1957

1958 1959 1960 1961 1962
    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;
1963

1964 1965
      if (time_diff < timing_info.time_min)
        timing_info.time_min = time_diff;
1966

1967 1968
      if (time_diff > timing_info.time_max)
        timing_info.time_max = time_diff;
1969

1970 1971 1972 1973 1974 1975
      timing_info.time_avg += time_diff;
    }

    timing_info.n_samples++;

    if ((slot&1) == 1) {
1976
      // odd slot
1977
#ifdef EXMIMO
1978
      int sf = ((slot>>1)+1)%10;
Raymond Knopp's avatar
 
Raymond Knopp committed
1979
#else
1980
      int sf = hw_subframe;
Raymond Knopp's avatar
 
Raymond Knopp committed
1981
#endif
1982 1983
      if (frame>50) {
	for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1984
#ifdef EXMIMO
1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999
	  
	  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);
2000
	      exit_fun("nothing to add");
2001 2002 2003
	    }
	  }
	  
Raymond Knopp's avatar
 
Raymond Knopp committed
2004 2005
#endif

2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028
	  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
2029
      }
2030 2031 2032 2033
    }

#ifdef EXMIMO
    slot++;
2034

2035 2036 2037 2038
    if (slot == 20) {
      frame++;
      slot = 0;
    }
2039

Raymond Knopp's avatar
 
Raymond Knopp committed
2040
#else
2041 2042
    hw_subframe++;
    slot += 2;
2043

2044
    if (hw_subframe == NUM_ENB_THREADS) {
2045
      // the radio frame is complete, start over
2046 2047 2048 2049
      hw_subframe = 0;
      frame++;
      slot = 1;
    }
2050 2051

#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2052

2053
#if defined(ENABLE_ITTI)
2054
    itti_update_lte_time( frame, slot );
2055
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2056
  }
2057 2058

eNB_thread_cleanup:
Raymond Knopp's avatar
 
Raymond Knopp committed
2059
#ifdef DEBUG_THREADS
2060
  printf( "eNB_thread: finished, ran %d times.\n", frame );
Raymond Knopp's avatar
 
Raymond Knopp committed
2061
#endif
2062

2063
#ifdef HARD_RT
Raymond Knopp's avatar
 
Raymond Knopp committed
2064
  rt_make_soft_real_time();
2065 2066
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
2067
#ifdef DEBUG_THREADS
2068
  printf( "Exiting eNB_thread ..." );
Raymond Knopp's avatar
 
Raymond Knopp committed
2069 2070
#endif
  // clean task
2071
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
2072
  rt_task_delete(task);
2073
#endif
2074 2075

  eNB_thread_status = 0;
2076

2077
  // print_difftimes();
2078

2079
  return &eNB_thread_status;
Raymond Knopp's avatar
 
Raymond Knopp committed
2080
}
2081

2082

Raymond Knopp's avatar
 
Raymond Knopp committed
2083

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2084

2085 2086
static void get_options (int argc, char **argv)
{
2087 2088 2089
  int c;
  //  char                          line[1000];
  //  int                           l;
2090
  int k,i;//,j,k;
2091
#if defined(OAI_USRP) || defined(CPRIGW)
2092
  int clock_src;
2093
#endif
2094 2095 2096 2097 2098
  int CC_id;
#ifdef EXMIMO
  char rxg_fname[256], line[1000];
  FILE *rxg_fd;
  int l;
2099
#endif
2100 2101 2102



2103 2104

  const Enb_properties_array_t *enb_properties;
2105

2106 2107
  enum long_option_e {
    LONG_OPTION_START = 0x100, /* Start after regular single char options */
2108
    LONG_OPTION_RF_CONFIG_FILE,
2109 2110 2111 2112 2113
    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,
2114
    LONG_OPTION_NO_L2_CONNECT,
Raymond Knopp's avatar
 
Raymond Knopp committed
2115
    LONG_OPTION_CALIB_PRACH_TX,
2116 2117
    LONG_OPTION_RXGAIN,
    LONG_OPTION_TXGAIN,
2118
    LONG_OPTION_SCANCARRIER,
2119 2120
    LONG_OPTION_MAXPOWER,
    LONG_OPTION_DUMP_FRAME,
2121 2122
    LONG_OPTION_LOOPMEMORY,
    LONG_OPTION_PHYTEST
2123
  };
2124

2125
  static const struct option long_options[] = {
2126
    {"rf-config-file",required_argument,  NULL, LONG_OPTION_RF_CONFIG_FILE},
2127 2128 2129 2130 2131 2132
    {"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
2133 2134 2135 2136
    {"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},
2137
    {"ue-max-power",   required_argument,  NULL, LONG_OPTION_MAXPOWER},
2138 2139
    {"ue-dump-frame", no_argument, NULL, LONG_OPTION_DUMP_FRAME},
    {"loop-memory", required_argument, NULL, LONG_OPTION_LOOPMEMORY},
2140
    {"phy-test", no_argument, NULL, LONG_OPTION_PHYTEST},
2141 2142 2143
    {NULL, 0, NULL, 0}
  };

2144
  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) {
2145
    switch (c) {
2146
    case LONG_OPTION_RF_CONFIG_FILE:
2147 2148 2149 2150 2151 2152
      if ((strcmp("null", optarg) == 0) || (strcmp("NULL", optarg) == 0)) {
	printf("no configuration filename is provided\n");
      }
      else if (strlen(optarg)<=1024){
	strcpy(rf_config_file,optarg);
      }else {
2153 2154 2155 2156
         printf("Configuration filename is too long\n");
         exit(-1);   
      }
      break;
2157 2158 2159 2160
    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];
2161
      break;
2162 2163 2164 2165
    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;
2166

2167 2168 2169 2170 2171
    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;
2172

2173 2174 2175 2176
    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
2177
      break;
2178

2179 2180 2181 2182 2183
    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;
2184

2185 2186 2187
    case LONG_OPTION_DEBUG_UE_PRACH:
      mode = debug_prach;
      break;
2188

2189 2190 2191
    case LONG_OPTION_NO_L2_CONNECT:
      mode = no_L2_connect;
      break;
2192

Raymond Knopp's avatar
 
Raymond Knopp committed
2193 2194 2195 2196
    case LONG_OPTION_CALIB_PRACH_TX:
      mode = calib_prach_tx;
      break;

2197
    case LONG_OPTION_RXGAIN:
2198 2199
      for (i=0; i<4; i++)
        rx_gain[0][i] = atof(optarg);
2200

2201
      break;
2202

2203 2204 2205
    case LONG_OPTION_TXGAIN:
      for (i=0; i<4; i++)
        tx_gain[0][i] = atof(optarg);
2206

2207
      break;
2208

2209 2210 2211 2212 2213
    case LONG_OPTION_SCANCARRIER:
      UE_scan_carrier=1;

      break;

2214 2215 2216 2217 2218 2219
    case LONG_OPTION_LOOPMEMORY:
      mode=loop_through_memory;
      input_fd = fopen(optarg,"r");
      AssertFatal(input_fd != NULL,"Please provide an input file\n");
      break;

2220 2221 2222 2223
    case LONG_OPTION_DUMP_FRAME:
      mode = rx_dump_frame;
      break;
      
2224 2225 2226
    case LONG_OPTION_PHYTEST:
      phy_test = 1;
      break;
2227
      
2228 2229 2230 2231
    case 'A':
      timing_advance = atoi (optarg);
      break;

2232
    case 'C':
2233 2234 2235 2236 2237 2238
      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]);
2239
      }
2240

2241
      UE_scan=0;
2242

2243
      break;
2244

Florian Kaltenberger's avatar
Florian Kaltenberger committed
2245 2246 2247 2248
    case 'a':
      chain_offset = atoi(optarg);
      break;

2249 2250 2251 2252
    case 'd':
#ifdef XFORMS
      do_forms=1;
      printf("Running with XFORMS!\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2253
#endif
2254
      break;
2255 2256 2257 2258
      
    case 'E':
      threequarter_fs=1;
      break;
2259

2260 2261 2262
    case 'K':
#if defined(ENABLE_ITTI)
      itti_dump_file = strdup(optarg);
2263
#else
2264
      printf("-K option is disabled when ENABLE_ITTI is not defined\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2265
#endif
2266
      break;
2267

2268 2269 2270
    case 'O':
      conf_config_file_name = optarg;
      break;
2271

2272 2273 2274
    case 'U':
      UE_flag = 1;
      break;
2275

2276 2277 2278
    case 'm':
      target_dl_mcs = atoi (optarg);
      break;
2279

2280 2281 2282
    case 't':
      target_ul_mcs = atoi (optarg);
      break;
2283

2284 2285 2286 2287 2288 2289 2290
    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");
      /*
2291 2292 2293
      if (optarg == NULL){
      in_ip[0] =NULL;
      printf("Enabling OPT for wireshark for local interface");
2294
      } else {
2295 2296 2297
      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);
2298 2299 2300
      }
      */
      break;
2301

2302
    case 'P':
2303 2304
      opt_type = OPT_PCAP;
      opt_enabled=1;
2305 2306 2307 2308 2309

      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");
2310
      } else {
2311 2312 2313
        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);
2314
      }
2315 2316 2317

      break;

Raymond Knopp's avatar
 
Raymond Knopp committed
2318 2319 2320
    case 'V':
      ouput_vcd = 1;
      break;
2321

Raymond Knopp's avatar
 
Raymond Knopp committed
2322
    case  'q':
Raymond Knopp's avatar
 
Raymond Knopp committed
2323 2324
      opp_enabled = 1;
      break;
2325

Raymond Knopp's avatar
 
Raymond Knopp committed
2326 2327 2328
    case  'R' :
      online_log_messages =1;
      break;
2329

Raymond Knopp's avatar
 
Raymond Knopp committed
2330
    case 'r':
2331
      UE_scan = 0;
2332

2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358
      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
2359
      }
2360

2361
      break;
2362

Raymond Knopp's avatar
 
Raymond Knopp committed
2363
    case 's':
2364
#if defined(OAI_USRP) || defined(CPRIGW)
Raymond Knopp's avatar
 
Raymond Knopp committed
2365 2366

      clock_src = atoi(optarg);
2367

Raymond Knopp's avatar
 
Raymond Knopp committed
2368
      if (clock_src == 0) {
2369 2370 2371 2372 2373
        //  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
2374
      }
2375

Raymond Knopp's avatar
 
Raymond Knopp committed
2376 2377 2378 2379
#else
      printf("Note: -s not defined for ExpressMIMO2\n");
#endif
      break;
2380

2381 2382 2383 2384
    case 'S':
      exit_missed_slots=0;
      printf("Skip exit for missed slots\n");
      break;
2385

2386
    case 'g':
Raymond Knopp's avatar
 
Raymond Knopp committed
2387
      glog_level=atoi(optarg); // value between 1 - 9
2388
      break;
2389 2390

    case 'F':
2391
#ifdef EXMIMO
2392 2393
      sprintf(rxg_fname,"%srxg.lime",optarg);
      rxg_fd = fopen(rxg_fname,"r");
2394

2395
      if (rxg_fd) {
2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413
        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);

2414
#endif
2415
      break;
2416

2417 2418 2419
    case 'G':
      glog_verbosity=atoi(optarg);// value from 0, 0x5, 0x15, 0x35, 0x75
      break;
2420

2421 2422
    case 'x':
      transmission_mode = atoi(optarg);
2423

2424 2425
      if (transmission_mode > 7) {
        printf("Transmission mode %d not supported for the moment\n",transmission_mode);
2426
        exit(-1);
2427
      }
2428
      break;
2429

2430 2431 2432
    case 'T':
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) 
	frame_parms[CC_id]->frame_type = TDD;
2433
      break;
2434

2435 2436 2437 2438
    case 'h':
      help ();
      exit (-1);
       
Raymond Knopp's avatar
 
Raymond Knopp committed
2439
    default:
2440 2441
      help ();
      exit (-1);
Raymond Knopp's avatar
 
Raymond Knopp committed
2442
      break;
2443 2444
    }
  }
2445

Raymond Knopp's avatar
 
Raymond Knopp committed
2446 2447
  if (UE_flag == 0)
    AssertFatal(conf_config_file_name != NULL,"Please provide a configuration file\n");
2448 2449


Raymond Knopp's avatar
 
Raymond Knopp committed
2450
  if ((UE_flag == 0) && (conf_config_file_name != NULL)) {
2451
    int i,j;
2452

Raymond Knopp's avatar
 
Raymond Knopp committed
2453
    NB_eNB_INST = 1;
2454

Raymond Knopp's avatar
 
Raymond Knopp committed
2455 2456
    /* Read eNB configuration file */
    enb_properties = enb_config_init(conf_config_file_name);
2457

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

Raymond Knopp's avatar
 
Raymond Knopp committed
2462
    /* Update some simulation parameters */
2463
    for (i=0; i < enb_properties->number; i++) {
2464
      AssertFatal (MAX_NUM_CCs == enb_properties->properties[i]->nb_cc,
2465 2466 2467
                   "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);

2468 2469
      for (j=0; j<enb_properties->properties[i]->nb_rrh_gw; j++) {
	
2470 2471 2472 2473 2474 2475 2476 2477 2478 2479
	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));
	  
	  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;
2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496
	  eth_params->transp_preference         = enb_properties->properties[i]->rrh_gw_config[j].raw;	 
	  eth_params->iq_txshift                = enb_properties->properties[i]->rrh_gw_config[j].iq_txshift;
	  eth_params->tx_sample_advance         = enb_properties->properties[i]->rrh_gw_config[j].tx_sample_advance;
	  eth_params->tx_scheduling_advance     = enb_properties->properties[i]->rrh_gw_config[j].tx_scheduling_advance;
	  if (enb_properties->properties[i]->rrh_gw_config[j].exmimo == 1) {
	     eth_params->rf_preference          = EXMIMO_DEV;
	  } else if (enb_properties->properties[i]->rrh_gw_config[j].usrp_b200 == 1) {
	    eth_params->rf_preference          = USRP_B200_DEV;
	  } else if (enb_properties->properties[i]->rrh_gw_config[j].usrp_x300 == 1) {
	   eth_params->rf_preference          = USRP_X300_DEV;
	  } else if (enb_properties->properties[i]->rrh_gw_config[j].bladerf == 1) {
	    eth_params->rf_preference          = BLADERF_DEV;
	  } else if (enb_properties->properties[i]->rrh_gw_config[j].lmssdr == 1) {
	    //eth_params->rf_preference          = LMSSDR_DEV;
	  } else {
	    eth_params->rf_preference          = 0;
	  } 
2497 2498
	} else {
	  local_remote_radio = BBU_LOCAL_RADIO_HEAD; 
2499 2500 2501 2502
	}
	
      }

2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516
      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
2517 2518
      }

2519

2520 2521 2522
      init_all_otg(0);
      g_otg->seed = 0;
      init_seeds(g_otg->seed);
2523 2524 2525 2526 2527 2528 2529 2530 2531 2532

      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");
2533
      }
2534

2535
      init_predef_traffic(enb_properties->properties[i]->num_otg_elements, 1);
2536 2537


2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551
      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
2552 2553 2554 2555 2556 2557
# 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
2558 2559 2560
#if defined (ENABLE_SECURITY)
      osa_log_level                  = enb_properties->properties[i]->osa_log_level;
      osa_log_verbosity              = enb_properties->properties[i]->osa_log_verbosity;
2561
#endif
Florian Kaltenberger's avatar
Florian Kaltenberger committed
2562

Raymond Knopp's avatar
 
Raymond Knopp committed
2563
      // adjust the log
2564
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
2565 2566 2567 2568 2569 2570 2571 2572 2573 2574
        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
2575
      } // CC_id
2576
    }// i
2577 2578 2579 2580 2581 2582 2583 2584
  } 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
2585
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
2586
}
2587

2588 2589
int main( int argc, char **argv )
{
2590
  int i,aa,card=0;
Lionel Gauthier's avatar
Lionel Gauthier committed
2591
#if defined (XFORMS) || defined (EMOS) || defined (EXMIMO)
Raymond Knopp's avatar
 
Raymond Knopp committed
2592
  void *status;
2593
#endif
2594

Raymond Knopp's avatar
 
Raymond Knopp committed
2595
  int CC_id;
Raymond Knopp's avatar
 
Raymond Knopp committed
2596
  uint16_t Nid_cell = 0;
2597
  uint8_t  cooperation_flag=0,  abstraction_flag=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2598
  uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2;
2599 2600

#ifdef ENABLE_TCXO
Raymond Knopp's avatar
 
Raymond Knopp committed
2601
  unsigned int tcxo = 114;
2602 2603
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
2604
#if defined (XFORMS)
2605 2606
  int ret;
#endif
2607
#if defined (EMOS) || (! defined (RTAI))
Raymond Knopp's avatar
 
Raymond Knopp committed
2608
  int error_code;
2609
#endif
2610

2611 2612 2613 2614 2615
#ifdef DEBUG_CONSOLE
  setvbuf(stdout, NULL, _IONBF, 0);
  setvbuf(stderr, NULL, _IONBF, 0);
#endif

2616 2617 2618
  PHY_VARS_UE *UE[MAX_NUM_CCs];

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

2621
  memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
Raymond Knopp's avatar
 
Raymond Knopp committed
2622
  set_latency_target();
2623

2624
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2625 2626
    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 */
2627
    frame_parms[CC_id]->frame_type          = FDD;
Raymond Knopp's avatar
 
Raymond Knopp committed
2628 2629
    frame_parms[CC_id]->tdd_config          = 3;
    frame_parms[CC_id]->tdd_config_S        = 0;
2630 2631
    frame_parms[CC_id]->N_RB_DL             = 100;
    frame_parms[CC_id]->N_RB_UL             = 100;
Raymond Knopp's avatar
 
Raymond Knopp committed
2632
    frame_parms[CC_id]->Ncp                 = NORMAL;
Raymond Knopp's avatar
 
Raymond Knopp committed
2633 2634
    frame_parms[CC_id]->Ncp_UL              = NORMAL;
    frame_parms[CC_id]->Nid_cell            = Nid_cell;
Raymond Knopp's avatar
 
Raymond Knopp committed
2635
    frame_parms[CC_id]->num_MBSFN_config    = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2636 2637 2638
    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
2639
  }
2640

2641 2642 2643 2644 2645
  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];
2646
    //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
2647
  }
2648 2649
  logInit();
 
2650
  rf_config_file[0]='\0';
2651
  get_options (argc, argv); //Command-line options
2652 2653 2654 2655
  if (rf_config_file[0] == '\0')
    openair0_cfg[0].configFilename = NULL;
  else
    openair0_cfg[0].configFilename = rf_config_file;
2656 2657
  
  // initialize the log (see log.h for details)
Florian Kaltenberger's avatar
Florian Kaltenberger committed
2658 2659
  set_glog(glog_level, glog_verbosity);

2660 2661
  //randominit (0);
  set_taus_seed (0);
Raymond Knopp's avatar
 
Raymond Knopp committed
2662

2663 2664
  if (UE_flag==1) {
    printf("configuring for UE\n");
2665

2666 2667
    set_comp_log(HW,      LOG_DEBUG,  LOG_HIGH, 1);
    set_comp_log(PHY,     LOG_DEBUG,   LOG_HIGH, 1);
2668 2669 2670 2671 2672
    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);
2673
#if defined(ENABLE_ITTI)
2674
    set_comp_log(EMU,     LOG_INFO,   LOG_MED, 1);
2675
# if defined(ENABLE_USE_MME)
2676
    set_comp_log(NAS,     LOG_INFO,   LOG_HIGH, 1);
2677 2678
# endif
#endif
2679 2680
  } else {
    printf("configuring for eNB\n");
2681

2682 2683 2684 2685 2686 2687 2688 2689
    set_comp_log(HW,      hw_log_level, hw_log_verbosity, 1);
    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);
    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);
2690
#if defined(ENABLE_ITTI)
2691
    set_comp_log(EMU,     LOG_INFO,   LOG_MED, 1);
2692
# if defined(ENABLE_USE_MME)
2693 2694 2695 2696
    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);
2697
# endif
2698
#if defined(ENABLE_SECURITY)
2699
    set_comp_log(OSA,    osa_log_level,   osa_log_verbosity, 1);
2700
#endif
2701
#endif
2702
#ifdef LOCALIZATION
2703 2704 2705 2706 2707 2708 2709 2710 2711
    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
2712
    }
2713
  }
2714

Raymond Knopp's avatar
 
Raymond Knopp committed
2715 2716
  if (ouput_vcd) {
    if (UE_flag==1)
2717
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_UE.vcd");
Raymond Knopp's avatar
 
Raymond Knopp committed
2718
    else
2719
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_eNB.vcd");
Raymond Knopp's avatar
 
Raymond Knopp committed
2720
  }
2721

2722
  if (opp_enabled ==1){
2723
    reset_opp_meas();
2724 2725
  }
  cpuf=get_cpu_freq_GHz();
2726

2727
#if defined(ENABLE_ITTI)
2728

Raymond Knopp's avatar
 
Raymond Knopp committed
2729 2730
  if (UE_flag == 1) {
    log_set_instance_type (LOG_INSTANCE_UE);
2731
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
2732 2733
    log_set_instance_type (LOG_INSTANCE_ENB);
  }
2734

Raymond Knopp's avatar
 
Raymond Knopp committed
2735
  itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, itti_dump_file);
2736
 
2737 2738
  // initialize mscgen log after ITTI
  MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX);
2739 2740
#endif
 
2741 2742
  if (opt_type != OPT_NONE) {
    radio_type_t radio_type;
2743

2744 2745
    if (frame_parms[0]->frame_type == FDD)
      radio_type = RADIO_TYPE_FDD;
2746
    else
2747
      radio_type = RADIO_TYPE_TDD;
2748

2749 2750 2751
    if (init_opt(in_path, in_ip, NULL, radio_type) == -1)
      LOG_E(OPT,"failed to run OPT \n");
  }
2752

2753
#ifdef PDCP_USE_NETLINK
Raymond Knopp's avatar
 
Raymond Knopp committed
2754
  netlink_init();
2755 2756 2757
#if defined(PDCP_USE_NETLINK_QUEUES)
  pdcp_netlink_init();
#endif
2758 2759
#endif

2760
#if !defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
2761 2762 2763
  // to make a graceful exit when ctrl-c is pressed
  signal(SIGSEGV, signal_handler);
  signal(SIGINT, signal_handler);
2764
#endif
2765 2766

#ifndef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
2767 2768 2769 2770
  check_clock();
#endif

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

2774 2775 2776 2777 2778 2779 2780 2781 2782
    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
2783 2784 2785 2786 2787 2788 2789 2790
    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;
2791
    frame_parms[CC_id]->threequarter_fs = threequarter_fs;
2792 2793
    init_ul_hopping(frame_parms[CC_id]);
    init_frame_parms(frame_parms[CC_id],1);
2794 2795
    //   phy_init_top(frame_parms[CC_id]);
    phy_init_lte_top(frame_parms[CC_id]);
Raymond Knopp's avatar
 
Raymond Knopp committed
2796 2797 2798
  }


2799
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2800
    //init prach for openair1 test
2801
    frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22;
Raymond Knopp's avatar
 
Raymond Knopp committed
2802
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1;
2803
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2804 2805 2806
    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
2807
    // N_ZC = (prach_fmt <4)?839:139;
Raymond Knopp's avatar
 
Raymond Knopp committed
2808
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
2809 2810

  if (UE_flag==1) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2811 2812 2813
    NB_UE_INST=1;
    NB_INST=1;

Raymond Knopp's avatar
 
Raymond Knopp committed
2814 2815
    PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE**));
    PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_UE*)*MAX_NUM_CCs);
2816 2817

    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
2818 2819 2820 2821

      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]);
2822

2823 2824 2825 2826
      if (phy_test==1)
	UE[CC_id]->mac_enabled = 0;
      else 
	UE[CC_id]->mac_enabled = 1;
2827

2828 2829 2830 2831 2832 2833 2834 2835 2836 2837
      if (UE[CC_id]->mac_enabled == 0) {
	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
2838
      }
2839

2840
      UE[CC_id]->UE_scan = UE_scan;
2841
      UE[CC_id]->UE_scan_carrier = UE_scan_carrier;
2842 2843 2844
      UE[CC_id]->mode    = mode;

      compute_prach_seq(&UE[CC_id]->lte_frame_parms.prach_config_common,
2845 2846 2847
                        UE[CC_id]->lte_frame_parms.frame_type,
                        UE[CC_id]->X_u);

2848 2849 2850 2851
      if (UE[CC_id]->mac_enabled == 1) 
	UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1234;
      else
	UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1235;
2852

2853
#ifdef EXMIMO
2854 2855 2856 2857
      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
2858
      }
2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877

      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
2878
      }
2879

2880
#else
2881
      UE[CC_id]->rx_total_gain_dB =  (int)rx_gain[CC_id][0];
2882
#endif
2883

2884
      UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id];
2885

2886

2887
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
2888
      //N_TA_offset
2889
      if (UE[CC_id]->lte_frame_parms.frame_type == TDD) {
2890 2891 2892 2893 2894 2895 2896 2897
        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
2898
      }
2899
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
2900
      //already taken care of in lte-softmodem
2901
      UE[CC_id]->N_TA_offset = 0;
2902
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2903
    }
2904

Raymond Knopp's avatar
 
Raymond Knopp committed
2905 2906 2907 2908
    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;
2909 2910 2911



Raymond Knopp's avatar
 
Raymond Knopp committed
2912
    //  printf("tx_max_power = %d -> amp %d\n",tx_max_power,get_tx_amp(tx_max_power,tx_max_power));
2913 2914 2915 2916 2917 2918
  } 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++) {
2919
      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);
2920 2921
      PHY_vars_eNB_g[0][CC_id]->CC_id = CC_id;

2922 2923 2924 2925
      if (phy_test==1)
	PHY_vars_eNB_g[0][CC_id]->mac_enabled = 0;
      else 
	PHY_vars_eNB_g[0][CC_id]->mac_enabled = 1;
2926

2927 2928 2929 2930 2931 2932 2933 2934 2935 2936
      if (PHY_vars_eNB_g[0][CC_id]->mac_enabled == 0) {
	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;
	}
2937 2938 2939 2940 2941
      }

      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
2942

2943
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
2944

2945
      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
2946

2947
#else
2948 2949 2950
      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
2951

2952 2953 2954
      // 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
2955

2956
#endif
2957

2958
#ifdef EXMIMO
2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969

      //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
2970
      }
2971

2972
#else
2973
      //already taken care of in lte-softmodem.c
2974 2975
      PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 0;
#endif
2976

2977
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
2978 2979


2980 2981 2982 2983 2984 2985 2986 2987 2988
    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;

  }
2989 2990 2991 2992
#ifndef RTAI
  fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx);
  cpuf=get_cpu_freq_GHz();
#endif 
2993

Raymond Knopp's avatar
 
Raymond Knopp committed
2994
  dump_frame_parms(frame_parms[0]);
2995

2996 2997 2998
  for (card=0; card<MAX_CARDS; card++) {

    if(frame_parms[0]->N_RB_DL == 100) {
2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010
      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;
      }
3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026
    } 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;
    }
3027 3028 3029 3030 3031 3032

    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
3033

3034 3035 3036 3037 3038 3039
    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;    
    }
3040

3041
    printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card,
3042 3043
           ((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
3044 3045
    openair0_cfg[card].Mod_id = 0;
#ifdef ETHERNET
3046 3047

    if (UE_flag) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3048
      printf("ETHERNET: Configuring UE ETH for %s:%d\n",rrh_UE_ip,rrh_UE_port);
3049
      openair0_cfg[card].remote_addr   = &rrh_UE_ip[0];
3050
      openair0_cfg[card].remote_port = rrh_UE_port;
3051 3052
    } 

3053
    openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL;
Raymond Knopp's avatar
 
Raymond Knopp committed
3054
#endif
3055

3056
    // in the case of the USRP, the following variables need to be initialized before the init
3057
    // since the USRP only supports one CC (for the moment), we initialize all the cards with first CC.
3058
    // in the case of EXMIMO2, these values are overwirtten in the function setup_eNB/UE_buffer
3059
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3060 3061
    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));
3062 3063

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

3065 3066 3067 3068 3069 3070 3071 3072
      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]);
      
3073
      openair0_cfg[card].autocal[i] = 1;
3074
      openair0_cfg[card].tx_gain[i] = tx_gain[0][i];
3075 3076 3077 3078
      if (UE_flag == 0) {
	openair0_cfg[card].rx_gain[i] = PHY_vars_eNB_g[0][0]->rx_total_gain_eNB_dB;
      }
      else {
3079
	openair0_cfg[card].rx_gain[i] = PHY_vars_UE_g[0][0]->rx_total_gain_dB;
3080
      }
3081

3082
#if 0  // UHD 3.8     
3083 3084
      switch(frame_parms[0]->N_RB_DL) {
      case 6:
3085
        openair0_cfg[card].rx_gain[i] -= 12;
3086 3087
        break;

3088
      case 25:
3089
        openair0_cfg[card].rx_gain[i] -= 6;
3090 3091
        break;

3092
      case 50:
3093 3094 3095 3096 3097
        openair0_cfg[card].rx_gain[i] -= 3;
        break;

      case 100:
        openair0_cfg[card].rx_gain[i] -= 0;
3098 3099
        break;

3100
      default:
3101
        break;
3102
      }
3103
#endif      
3104

Raymond Knopp's avatar
 
Raymond Knopp committed
3105
    }
3106

3107
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3108
  }
3109 3110 3111 3112 3113 3114
  /* 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
3115
  openair0_cfg[0].log_level = glog_level;
3116

3117 3118 3119 3120 3121 3122 3123 3124 3125 3126
  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);
      }
3127
    }
3128 3129 3130 3131 3132 3133 3134 3135 3136 3137
    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);
      }
3138 3139 3140 3141
    }
    else if (mode==loop_through_memory) {    
    }
  }   
3142
  
3143
  printf("Done\n");
3144 3145 3146

  mac_xface = malloc(sizeof(MAC_xface));

Raymond Knopp's avatar
 
Raymond Knopp committed
3147
  int eMBMS_active=0;
3148
  
Raymond Knopp's avatar
 
Raymond Knopp committed
3149
  l2_init(frame_parms[0],eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL,
3150 3151 3152
	  0,// cba_group_active
	  0); // HO flag
  
Raymond Knopp's avatar
 
Raymond Knopp committed
3153
  mac_xface->macphy_exit = &exit_fun;
3154

winckel's avatar
winckel committed
3155
#if defined(ENABLE_ITTI)
3156

Raymond Knopp's avatar
 
Raymond Knopp committed
3157
  if (create_tasks(UE_flag ? 0 : 1, UE_flag ? 1 : 0) < 0) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3158
    printf("cannot create ITTI tasks\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3159 3160
    exit(-1); // need a softer mode
  }
3161

Raymond Knopp's avatar
 
Raymond Knopp committed
3162
  printf("ITTI tasks created\n");
winckel's avatar
winckel committed
3163
#endif
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3164

3165 3166 3167 3168 3169 3170 3171 3172
  if (phy_test==0) {
    if (UE_flag==1) {
      printf("Filling UE band info\n");
      fill_ue_band_info();
      mac_xface->dl_phy_sync_success (0, 0, 0, 1);
    } else
      mac_xface->mrbch_phy_sync_failure (0, 0, 0);
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
3173

3174
  /* #ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
3175 3176 3177 3178 3179 3180
  //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
3181 3182 3183 3184 3185 3186
  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
3187 3188 3189
  }
  init_predef_traffic(UE_flag ? 1 : 0, UE_flag ? 0 : 1);
  //  }
3190
  #endif */
Raymond Knopp's avatar
 
Raymond Knopp committed
3191

3192
#ifdef EXMIMO
3193
  number_of_cards = openair0_num_detected_cards;
3194 3195
#else
  number_of_cards = 1;
3196
#endif
3197

3198

3199

3200
  for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3201
    rf_map[CC_id].card=0;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3202
    rf_map[CC_id].chain=CC_id+chain_offset;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3203
  }
3204

Raymond Knopp's avatar
 
Raymond Knopp committed
3205 3206
  // connect the TX/RX buffers
  if (UE_flag==1) {
3207
#ifdef OAI_USRP
3208
    openair_daq_vars.timing_advance = timing_advance;
3209
#else
3210
    openair_daq_vars.timing_advance = 160;
3211
#endif
3212
    if (setup_ue_buffers(UE,&openair0_cfg[0],rf_map)!=0) {
3213 3214 3215
      printf("Error setting up eNB buffer\n");
      exit(-1);
    }
3216

3217
    printf("Setting UE buffer to all-RX\n");
3218

3219
    // Set LSBs for antenna switch (ExpressMIMO)
3220
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3221
      for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++)
3222 3223
        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
3224
    }
3225

3226 3227
    if (input_fd) {
      printf("Reading in from file to antenna buffer %d\n",0);
3228 3229 3230 3231 3232
      if (fread(UE[0]->lte_ue_common_vars.rxdata[0],
	        sizeof(int32_t),
	        frame_parms[0]->samples_per_tti*10,
	        input_fd) != frame_parms[0]->samples_per_tti*10)
        printf("error reading from file\n");
3233
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3234
    //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX;
3235
  } else {
3236
    openair_daq_vars.timing_advance = 0;
3237

3238 3239 3240 3241
    if (setup_eNB_buffers(PHY_vars_eNB_g[0],&openair0_cfg[0],rf_map)!=0) {
      printf("Error setting up eNB buffer\n");
      exit(-1);
    }
3242

3243
    printf("Setting eNB buffer to all-RX\n");
3244

3245
    // Set LSBs for antenna switch (ExpressMIMO)
3246
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3247
      for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++)
3248 3249
        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
3250
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3251
  }
3252

3253
#ifdef EXMIMO
3254
  openair0_config(&openair0_cfg[0],UE_flag);
Raymond Knopp's avatar
 
Raymond Knopp committed
3255 3256
#endif

3257
  /*
Raymond Knopp's avatar
 
Raymond Knopp committed
3258 3259
      for (ant=0;ant<4;ant++)
      p_exmimo_config->rf.do_autocal[ant] = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3260
  */
3261 3262

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3265 3266 3267 3268 3269 3270
  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);
3271
  else
Raymond Knopp's avatar
 
Raymond Knopp committed
3272
    printf("[OPENAIR][SCHED][INIT] Problem creating EMOS FIFO %d, error_code %d\n",CHANSOUNDER_FIFO_MINOR,error_code);
3273

3274 3275
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3276
  mlockall(MCL_CURRENT | MCL_FUTURE);
3277 3278

#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3279
  // make main thread LXRT soft realtime
3280
  /* task = */ rt_task_init_schmod(nam2num("MAIN"), 9, 0, 0, SCHED_FIFO, 0xF);
Raymond Knopp's avatar
 
Raymond Knopp committed
3281 3282 3283 3284 3285

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3288 3289
  pthread_cond_init(&sync_cond,NULL);
  pthread_mutex_init(&sync_mutex, NULL);
3290

3291
  /*  this is moved to the eNB main thread */ 
3292

3293
//#if defined(ENABLE_ITTI)
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3294
  // Wait for eNB application initialization to be complete (eNB registration to MME)
3295 3296 3297 3298 3299
  //  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
3300

Raymond Knopp's avatar
 
Raymond Knopp committed
3301 3302

  // this starts the DMA transfers
3303
#ifdef EXMIMO
3304

Raymond Knopp's avatar
 
Raymond Knopp committed
3305
  if (UE_flag!=1)
3306
    for (card=0; card<openair0_num_detected_cards; card++)
3307
      openair0_start_rt_acquisition(card);
3308

Raymond Knopp's avatar
 
Raymond Knopp committed
3309
#endif
3310 3311

#ifdef XFORMS
3312 3313
  int UE_id;

Raymond Knopp's avatar
 
Raymond Knopp committed
3314 3315
  if (do_forms==1) {
    fl_initialize (&argc, argv, NULL, 0, 0);
3316 3317

    if (UE_flag==0) {
3318
      form_stats_l2 = create_form_stats_form();
3319 3320 3321
      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");
3322 3323

      for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336
	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");
	  }
	}
3337
      }
3338
    } else {
3339 3340 3341 3342 3343 3344 3345
      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
3346
      if (openair_daq_vars.use_ia_receiver) {
3347 3348 3349 3350 3351
        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
3352 3353 3354
      }
    }

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

3357 3358
    if (ret == 0)
      pthread_setname_np( forms_thread, "xforms" );
3359

Raymond Knopp's avatar
 
Raymond Knopp committed
3360 3361
    printf("Scope thread created, ret=%d\n",ret);
  }
3362

3363 3364 3365
#endif

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3366 3367
  ret = pthread_create(&thread3, NULL, emos_thread, NULL);
  printf("EMOS thread created, ret=%d\n",ret);
jiangx's avatar
jiangx committed
3368 3369
  ret = pthread_create(&thread4, NULL, gps_thread, NULL);
  printf("GPS thread created, ret=%d\n",ret);
3370 3371
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3372
  rt_sleep_ns(10*FRAME_PERIOD);
3373 3374

#ifndef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3375
  pthread_attr_init (&attr_dlsch_threads);
3376
  pthread_attr_setstacksize(&attr_dlsch_threads,4*PTHREAD_STACK_MIN);
3377

3378
  pthread_attr_init (&attr_UE_thread);
3379
  pthread_attr_setstacksize(&attr_UE_thread,8192);//5*PTHREAD_STACK_MIN);
3380

3381
#ifndef LOWLATENCY
3382 3383
  sched_param_UE_thread.sched_priority = sched_get_priority_max(SCHED_FIFO);
  pthread_attr_setschedparam(&attr_UE_thread,&sched_param_UE_thread);
3384
  sched_param_dlsch.sched_priority = sched_get_priority_max(SCHED_FIFO); //OPENAIR_THREAD_PRIORITY;
Raymond Knopp's avatar
 
Raymond Knopp committed
3385 3386
  pthread_attr_setschedparam  (&attr_dlsch_threads, &sched_param_dlsch);
  pthread_attr_setschedpolicy (&attr_dlsch_threads, SCHED_FIFO);
3387
  printf("Setting eNB_thread FIFO scheduling policy with priority %d \n", sched_param_dlsch.sched_priority);
3388
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3389

3390 3391
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3392 3393
  // start the main thread
  if (UE_flag == 1) {
3394
    printf("Intializing UE Threads ...\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3395
    init_UE_threads();
3396 3397 3398 3399 3400
#ifdef DLSCH_THREAD
    init_rx_pdsch_thread();
    rt_sleep_ns(FRAME_PERIOD/10);
    init_dlsch_threads();
#endif
3401

3402
    sleep(1);
3403
#ifdef RTAI
3404
    main_ue_thread = rt_thread_create(UE_thread, NULL, 100000000);
3405
#else
3406
    error_code = pthread_create(&main_ue_thread, &attr_UE_thread, UE_thread, NULL);
3407

Raymond Knopp's avatar
 
Raymond Knopp committed
3408 3409 3410
    if (error_code!= 0) {
      LOG_D(HW,"[lte-softmodem.c] Could not allocate UE_thread, error %d\n",error_code);
      return(error_code);
3411
    } else {
3412 3413
      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
3414
    }
3415

3416
#endif
3417
    printf("UE threads created\n");
3418 3419 3420 3421 3422 3423 3424 3425 3426 3427
#ifdef USE_MME

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

#endif



3428
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
3429 3430
    if (multi_thread>0) {
      init_eNB_proc();
3431
      sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3432 3433
      LOG_D(HW,"[lte-softmodem.c] eNB threads created\n");
    }
3434

3435
    printf("Creating main eNB_thread \n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3436
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3437
    main_eNB_thread = rt_thread_create(eNB_thread, NULL, PTHREAD_STACK_MIN);
Raymond Knopp's avatar
 
Raymond Knopp committed
3438
#else
3439
    error_code = pthread_create( &main_eNB_thread, &attr_dlsch_threads, eNB_thread, NULL );
3440

Raymond Knopp's avatar
 
Raymond Knopp committed
3441 3442 3443
    if (error_code!= 0) {
      LOG_D(HW,"[lte-softmodem.c] Could not allocate eNB_thread, error %d\n",error_code);
      return(error_code);
3444
    } else {
3445 3446
      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
3447
    }
3448

Raymond Knopp's avatar
 
Raymond Knopp committed
3449 3450
#endif
  }
3451

Raymond Knopp's avatar
 
Raymond Knopp committed
3452
  // Sleep to allow all threads to setup
Raymond Knopp's avatar
 
Raymond Knopp committed
3453
  sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3454

3455

3456

3457
#ifndef EXMIMO
3458

Raymond Knopp's avatar
 
Raymond Knopp committed
3459
#ifndef USRP_DEBUG
3460
  if (mode!=loop_through_memory)
navid's avatar
navid committed
3461 3462 3463
    if (openair0.trx_start_func(&openair0) != 0 ) 
      LOG_E(HW,"Could not start the device\n");

Raymond Knopp's avatar
 
Raymond Knopp committed
3464
#endif
3465

3466 3467
#endif

3468
  printf("Sending sync to all threads\n");
3469

Raymond Knopp's avatar
 
Raymond Knopp committed
3470
  pthread_mutex_lock(&sync_mutex);
3471
  sync_var=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3472 3473
  pthread_cond_broadcast(&sync_cond);
  pthread_mutex_unlock(&sync_mutex);
3474

Raymond Knopp's avatar
 
Raymond Knopp committed
3475 3476 3477
  // wait for end of program
  printf("TYPE <CTRL-C> TO TERMINATE\n");
  //getchar();
3478 3479

#if defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
3480 3481
  printf("Entering ITTI signals handler\n");
  itti_wait_tasks_end();
3482
  oai_exit=1;
3483
#else
3484

Raymond Knopp's avatar
 
Raymond Knopp committed
3485 3486
  while (oai_exit==0)
    rt_sleep_ns(FRAME_PERIOD);
3487

3488
#endif
3489

Raymond Knopp's avatar
 
Raymond Knopp committed
3490
  // stop threads
3491
#ifdef XFORMS
Raymond Knopp's avatar
 
Raymond Knopp committed
3492
  printf("waiting for XFORMS thread\n");
3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506

  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++) {
3507 3508 3509 3510
	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
3511
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
3512
    }
3513 3514
  }

3515 3516
#endif

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3519 3520
  // cleanup
  if (UE_flag == 1) {
3521
#ifdef EXMIMO
3522
#ifdef RTAI
3523
    rt_thread_join(main_ue_thread);
3524
#else
3525
    pthread_join(main_ue_thread,&status);
3526 3527
#endif
#ifdef DLSCH_THREAD
Raymond Knopp's avatar
 
Raymond Knopp committed
3528 3529
    cleanup_dlsch_threads();
    cleanup_rx_pdsch_thread();
3530
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3531
#endif
3532
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
3533
#ifdef DEBUG_THREADS
Raymond Knopp's avatar
 
Raymond Knopp committed
3534
    printf("Joining eNB_thread ...");
Raymond Knopp's avatar
 
Raymond Knopp committed
3535
#endif
3536
#ifdef RTAI
3537
    rt_thread_join(main_eNB_thread);
3538
#else
3539 3540
    int *eNB_thread_status_p;
    int result = pthread_join( main_eNB_thread, (void**)&eNB_thread_status_p );
Raymond Knopp's avatar
 
Raymond Knopp committed
3541
#ifdef DEBUG_THREADS
3542

3543
    if (result != 0) {
3544
      printf( "\nError joining main_eNB_thread.\n" );
3545
    } else {
3546 3547 3548 3549 3550
      if (eNB_thread_status_p) {
        printf( "status %d\n", *eNB_thread_status_p );
      } else {
        printf( "The thread was killed. No status available.\n");
      }
3551
    }
3552

3553 3554
#else
    UNUSED(result);
3555 3556
#endif // DEBUG_THREADS
#endif // RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3557

Raymond Knopp's avatar
 
Raymond Knopp committed
3558 3559 3560
    if (multi_thread>0) {
      printf("Killing eNB processing threads\n");
      kill_eNB_proc();
Raymond Knopp's avatar
 
Raymond Knopp committed
3561
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3562
  }
3563

3564

3565
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3566
  stop_rt_timer();
3567
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3568 3569
  pthread_cond_destroy(&sync_cond);
  pthread_mutex_destroy(&sync_mutex);
3570

3571

3572
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3573
  printf("stopping card\n");
3574
  openair0_stop(0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3575 3576
  printf("closing openair0_lib\n");
  openair0_close();
navid's avatar
navid committed
3577 3578
#else
  openair0.trx_end_func(&openair0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3579
#endif
3580 3581

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3582 3583 3584
  printf("waiting for EMOS thread\n");
  pthread_cancel(thread3);
  pthread_join(thread3,&status);
jiangx's avatar
jiangx committed
3585 3586 3587
  printf("waiting for GPS thread\n");
  pthread_cancel(thread4);
  pthread_join(thread4,&status);
3588 3589 3590
#endif

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3591 3592
  error_code = rtf_destroy(CHANSOUNDER_FIFO_MINOR);
  printf("[OPENAIR][SCHED][CLEANUP] EMOS FIFO closed, error_code %d\n", error_code);
3593 3594
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3595
  if (ouput_vcd)
3596
    VCD_SIGNAL_DUMPER_CLOSE();
3597

3598
  if (opt_enabled == 1)
3599
    terminate_opt();
3600

Raymond Knopp's avatar
 
Raymond Knopp committed
3601
  logClean();
3602

Raymond Knopp's avatar
 
Raymond Knopp committed
3603 3604
  return 0;
}
3605 3606


3607 3608 3609
/* 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
3610
   antennas are mapped to successive RF chains on the same card. */
3611 3612
int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs])
{
3613

3614
  int i, CC_id;
3615
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3616
  uint16_t N_TA_offset = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3617 3618
#else
  int j;
Raymond Knopp's avatar
 
Raymond Knopp committed
3619
#endif
3620
  LTE_DL_FRAME_PARMS *frame_parms;
3621

Raymond Knopp's avatar
 
Raymond Knopp committed
3622

3623 3624
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    if (phy_vars_eNB[CC_id]) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3625 3626
      frame_parms = &(phy_vars_eNB[CC_id]->lte_frame_parms);
      printf("setup_eNB_buffers: frame_parms = %p\n",frame_parms);
3627
    } else {
3628 3629
      printf("phy_vars_eNB[%d] not initialized\n", CC_id);
      return(-1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3630
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3631

3632
#ifndef EXMIMO
3633

3634 3635
    if (frame_parms->frame_type == TDD) {
      if (frame_parms->N_RB_DL == 100)
3636
        N_TA_offset = 624;
3637
      else if (frame_parms->N_RB_DL == 50)
3638
        N_TA_offset = 624/2;
3639
      else if (frame_parms->N_RB_DL == 25)
3640
        N_TA_offset = 624/4;
Raymond Knopp's avatar
 
Raymond Knopp committed
3641
    }
3642

Raymond Knopp's avatar
 
Raymond Knopp committed
3643
#endif
3644

Raymond Knopp's avatar
 
Raymond Knopp committed
3645
    // replace RX signal buffers with mmaped HW versions
3646
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3647 3648 3649
    openair0_cfg[CC_id].tx_num_channels = 0;
    openair0_cfg[CC_id].rx_num_channels = 0;

3650
    for (i=0; i<frame_parms->nb_antennas_rx; i++) {
3651 3652 3653
      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];
3654

3655
      if (openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i]) {
3656 3657 3658 3659 3660 3661
        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++;
3662
      }
3663

3664
      printf("rxdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]);
3665 3666 3667 3668

      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;
3669
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
3670
    }
3671 3672

    for (i=0; i<frame_parms->nb_antennas_tx; i++) {
3673 3674 3675
      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];
3676

3677
      if (openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i]) {
3678 3679 3680 3681 3682 3683
        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++;
3684
      }
3685

3686
      printf("txdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3687 3688 3689 3690

      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;
3691
      }
3692
    }
3693

3694
#else // not EXMIMO
3695 3696 3697
    rxdata = (int32_t**)malloc16(frame_parms->nb_antennas_rx*sizeof(int32_t*));
    txdata = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*));

3698
    for (i=0; i<frame_parms->nb_antennas_rx; i++) {
3699
      free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]);
3700
      rxdata[i] = (int32_t*)(32 + malloc16(32+openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation
3701
      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
3702
      memset(rxdata[i], 0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t));
3703
      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);
3704
      
Raymond Knopp's avatar
 
Raymond Knopp committed
3705
    }
3706 3707

    for (i=0; i<frame_parms->nb_antennas_tx; i++) {
3708
      free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3709
      txdata[i] = (int32_t*)(32 + malloc16(32 + openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation
3710
      phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i] = txdata[i];
3711
      memset(txdata[i],0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t));
3712
      printf("txdata[%d] @ %p\n", i, phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3713

Raymond Knopp's avatar
 
Raymond Knopp committed
3714
    }
3715

Raymond Knopp's avatar
 
Raymond Knopp committed
3716
#endif
3717
  }
3718

3719
  return(0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3720
}
3721

3722
void reset_opp_meas(void) {
3723 3724 3725
  int sfn;
  reset_meas(&softmodem_stats_mt);
  reset_meas(&softmodem_stats_hw);
3726
  
3727 3728 3729 3730 3731 3732
  for (sfn=0; sfn < 10; sfn++) {
    reset_meas(&softmodem_stats_tx_sf[sfn]);
    reset_meas(&softmodem_stats_rx_sf[sfn]);
  }
}

3733 3734
void print_opp_meas(void) {

3735 3736 3737
  int sfn=0;
  print_meas(&softmodem_stats_mt, "Main ENB Thread", NULL, NULL);
  print_meas(&softmodem_stats_hw, "HW Acquisation", NULL, NULL);
3738
  
3739 3740 3741 3742 3743
  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);
  }
}
3744 3745