lte-softmodem.c 121 KB
Newer Older
1
/*******************************************************************************
2
    OpenAirInterface
3
    Copyright(c) 1999 - 2014 Eurecom
4

5 6 7 8
    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
9 10


11 12 13 14
    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
15

16
    You should have received a copy of the GNU General Public License
17 18
    along with OpenAirInterface.The full GNU General Public License is
    included in this distribution in the file called "COPYING". If not,
19
    see <http://www.gnu.org/licenses/>.
20

21 22 23
   Contact Information
   OpenAirInterface Admin: openair_admin@eurecom.fr
   OpenAirInterface Tech : openair_tech@eurecom.fr
24
   OpenAirInterface Dev  : openair4g-devel@lists.eurecom.fr
25

ghaddab's avatar
ghaddab committed
26
   Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
27

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

/*! \file lte-softmodem.c
Raymond Knopp's avatar
 
Raymond Knopp committed
31
 * \brief main program to control HW and scheduling
32
 * \author R. Knopp, F. Kaltenberger, Navid Nikaein
Raymond Knopp's avatar
 
Raymond Knopp committed
33 34 35
 * \date 2012
 * \version 0.1
 * \company Eurecom
36
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr
Raymond Knopp's avatar
 
Raymond Knopp committed
37 38 39
 * \note
 * \warning
 */
Raymond Knopp's avatar
 
Raymond Knopp committed
40
#define _GNU_SOURCE
41 42 43 44 45 46 47 48
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sched.h>
49
#include <linux/sched.h>
50 51 52 53 54
#include <signal.h>
#include <execinfo.h>
#include <getopt.h>

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

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

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

#include "PHY/types.h"
66

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

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

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

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

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

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

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

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

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

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

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

#define FRAME_PERIOD    100000000ULL
#define DAQ_PERIOD      66667ULL

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

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

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


Raymond Knopp's avatar
 
Raymond Knopp committed
147

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

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

155 156 157 158
uint16_t runtime_phy_rx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100]
uint16_t runtime_phy_tx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100]
double cpuf;

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

#ifdef RTAI
171

172 173
static long                      main_eNB_thread;
static long                      main_ue_thread;
174

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

179
pthread_attr_t                  attr_dlsch_threads;
180 181
pthread_attr_t                  attr_UE_thread;

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

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

191

192 193


194
struct sched_param              sched_param_UE_thread;
195

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
212

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

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

223

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
234

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

238
static char                     threequarter_fs=0;
239

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

243
openair0_rf_map rf_map[MAX_NUM_CCs];
244

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

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

254 255
FILE *input_fd=NULL;

256

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

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

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

293 294
char   rf_config_file[1024];

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

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

#endif
302 303

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
326

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
363 364 365

#ifdef ETHERNET
char *rrh_UE_ip = "127.0.0.1";
366
int rrh_UE_port = 51000;
Raymond Knopp's avatar
 
Raymond Knopp committed
367 368
#endif

369 370 371 372 373
/* 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
374
char uecap_xer[1024],uecap_xer_in=0;
375 376
extern void *UE_thread(void *arg);
extern void init_UE_threads(void);
Raymond Knopp's avatar
 
Raymond Knopp committed
377

378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418
/*---------------------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
}

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

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

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

438 439 440 441
    // print out all the frames to stderr
    fprintf(stderr, "Error: signal %d:\n", sig);
    backtrace_symbols_fd(array, size, 2);
    exit(-1);
442 443
  } else {
    printf("trying to exit gracefully...\n");
444
    oai_exit = 1;
445 446
  }
}
447
#endif
448 449 450 451 452 453 454 455 456 457 458
#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");
459
  printf("  --rf-config-file Configuration file for front-end (e.g. LMS7002M)\n");
460 461 462 463
  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
464 465
  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");
466
  printf("  --no-L2-connect bypass L2 and upper layers\n");
467 468 469 470
  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");
471
  printf("  -C Set the downlink frequency for all component carriers\n");
472 473 474 475 476 477 478 479 480
  printf("  -d Enable soft scope and L1 and L2 stats (Xforms)\n");
  printf("  -F Calibrate the EXMIMO borad, available files: exmimo2_2arxg.lime exmimo2_2brxg.lime \n");
  printf("  -g Set the global log level, valide options: (9:trace, 8/7:debug, 6:info, 4:warn, 3:error)\n");
  printf("  -G Set the global log level \n");
  printf("  -h provides this help message!\n");
  printf("  -K Generate ITTI analyzser logs (similar to wireshark logs but with more details)\n");
  printf("  -m Set the maximum downlink MCS\n");
  printf("  -O eNB configuration file (located in targets/PROJECTS/GENERIC-LTE-EPC/CONF\n");
  printf("  -q Enable processing timing measurement of lte softmodem on per subframe basis \n");
kaltenbe's avatar
kaltenbe committed
481
  printf("  -r Set the PRB, valid values: 6, 25, 50, 100  \n");    
482 483
  printf("  -S Skip the missed slots/subframes \n");    
  printf("  -t Set the maximum uplink MCS\n");
484
  printf("  -T Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n");
485 486 487 488
  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);    
489

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

  oai_exit = 1;

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

  //rt_sleep_ns(FRAME_PERIOD);

  //exit (-1);
}

509

510
#ifdef XFORMS
511

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

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

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

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

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

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

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

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

558
# ifdef ENABLE_XFORMS_WRITE_STATS
559 560

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

565
#endif
566

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

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

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

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

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

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

603
    }
604

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

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

612
# ifdef ENABLE_XFORMS_WRITE_STATS
613

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

628
# endif
629

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

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

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

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

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

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

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

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

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

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

677 678 679

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

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

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

  pthread_exit((void*) arg);

}

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

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

721 722 723
  time_t timer;
  struct tm *now;

724
  struct sched_param sched_param;
725 726

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

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

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

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

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


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

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

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


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

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

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

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

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

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

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

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

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

}
#endif

832 833


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

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

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

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

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
864

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

874 875 876
      itti_receive_msg (TASK_L2L1, &message_p);

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

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

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

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
934

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

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

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
953

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

981 982 983 984 985
      // 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
986
      /*
987 988 989 990 991
      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
992
	}*/
993
      for (i=0; i<len; i++) {
994 995
        tx_offset = (int)slot_offset+time_offset[aa]+i;

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

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

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

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

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

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

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

1067 1068
  MSC_START_USE();

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

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

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

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

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

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

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

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

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

  mlockall(MCL_CURRENT | MCL_FUTURE);

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

1126
  while (!oai_exit) {
1127

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

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

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

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

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

    if (oai_exit) break;
1153

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

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

1177 1178 1179
      if (oai_exit)
        break;

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

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

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

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

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

1241 1242
  }

1243 1244


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

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

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

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


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

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

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

1287 1288
  MSC_START_USE();

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

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

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

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

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

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

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

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

  mlockall(MCL_CURRENT | MCL_FUTURE);

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

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

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

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

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

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

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

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

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

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

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

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

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

    proc->frame_rx++;
1399

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

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

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

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

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

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



Raymond Knopp's avatar
 
Raymond Knopp committed
1435

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

1573 1574
#ifdef DEBUG_THREADS

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

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

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


Raymond Knopp's avatar
 
Raymond Knopp committed
1597 1598


1599

Raymond Knopp's avatar
 
Raymond Knopp committed
1600

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

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

  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
1631

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

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

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

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

Lionel Gauthier's avatar
Lionel Gauthier committed
1658

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

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

1672
#endif
1673 1674
#endif

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

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

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

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

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

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

1705
  pthread_mutex_unlock(&sync_mutex);
1706

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

1709
  int frame = 0;
1710

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

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

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

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

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

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

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

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

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

    
1786
    }
1787

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

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

    delay_cnt = 0;
1796

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

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

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

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

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

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

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

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

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

1844
      clock_gettime( CLOCK_MONOTONIC, &trx_time0 );
1845

1846
       start_meas( &softmodem_stats_hw );
1847

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

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

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

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

1897

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

1916
        for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1917 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
          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;

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1952 1953

#endif // USRP
1954

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

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

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

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

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

    timing_info.n_samples++;

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

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

#ifdef EXMIMO
    slot++;
2033

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

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

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

#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2051

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

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

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

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

  eNB_thread_status = 0;
2075

2076
  // print_difftimes();
2077

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

2081

Raymond Knopp's avatar
 
Raymond Knopp committed
2082

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2083

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



2102 2103

  const Enb_properties_array_t *enb_properties;
2104

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

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

2141
  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) {
2142
    switch (c) {
2143 2144 2145 2146 2147 2148 2149 2150
    case LONG_OPTION_RF_CONFIG_FILE:
      if (strlen(optarg)<=1024)
         strcpy(rf_config_file,optarg);
      else {
         printf("Configuration filename is too long\n");
         exit(-1);   
      }
      break;
2151 2152 2153 2154
    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];
2155
      break;
2156 2157 2158 2159
    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;
2160

2161 2162 2163 2164 2165
    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;
2166

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

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

2179 2180 2181
    case LONG_OPTION_DEBUG_UE_PRACH:
      mode = debug_prach;
      break;
2182

2183 2184 2185
    case LONG_OPTION_NO_L2_CONNECT:
      mode = no_L2_connect;
      break;
2186

Raymond Knopp's avatar
 
Raymond Knopp committed
2187 2188 2189 2190
    case LONG_OPTION_CALIB_PRACH_TX:
      mode = calib_prach_tx;
      break;

2191
    case LONG_OPTION_RXGAIN:
2192 2193
      for (i=0; i<4; i++)
        rx_gain[0][i] = atof(optarg);
2194

2195
      break;
2196

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

2201
      break;
2202

2203 2204 2205 2206 2207
    case LONG_OPTION_SCANCARRIER:
      UE_scan_carrier=1;

      break;

2208 2209 2210 2211 2212 2213 2214 2215
    case LONG_OPTION_LOOPMEMORY:
      mode=loop_through_memory;
      input_fd = fopen(optarg,"r");
      AssertFatal(input_fd != NULL,"Please provide an input file\n");
      break;

   case LONG_OPTION_DUMP_FRAME:
     mode = rx_dump_frame;
2216
     break;   
2217 2218 2219 2220
    case 'A':
      timing_advance = atoi (optarg);
      break;

2221
    case 'C':
2222 2223 2224 2225 2226 2227
      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]);
2228
      }
2229

2230
      UE_scan=0;
2231

2232
      break;
2233

Florian Kaltenberger's avatar
Florian Kaltenberger committed
2234 2235 2236 2237
    case 'a':
      chain_offset = atoi(optarg);
      break;

2238 2239 2240 2241
    case 'd':
#ifdef XFORMS
      do_forms=1;
      printf("Running with XFORMS!\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2242
#endif
2243
      break;
2244 2245 2246 2247
      
    case 'E':
      threequarter_fs=1;
      break;
2248

2249 2250 2251
    case 'K':
#if defined(ENABLE_ITTI)
      itti_dump_file = strdup(optarg);
2252
#else
2253
      printf("-K option is disabled when ENABLE_ITTI is not defined\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2254
#endif
2255
      break;
2256

2257 2258 2259
    case 'O':
      conf_config_file_name = optarg;
      break;
2260

2261 2262 2263
    case 'U':
      UE_flag = 1;
      break;
2264

2265 2266 2267
    case 'm':
      target_dl_mcs = atoi (optarg);
      break;
2268

2269 2270 2271
    case 't':
      target_ul_mcs = atoi (optarg);
      break;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2272
#ifdef OPENAIR2
2273

2274 2275 2276 2277 2278 2279 2280
    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");
      /*
2281 2282 2283
      if (optarg == NULL){
      in_ip[0] =NULL;
      printf("Enabling OPT for wireshark for local interface");
2284
      } else {
2285 2286 2287
      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);
2288 2289 2290
      }
      */
      break;
2291

2292
    case 'P':
2293 2294
      opt_type = OPT_PCAP;
      opt_enabled=1;
2295 2296 2297 2298 2299

      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");
2300
      } else {
2301 2302 2303
        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);
2304
      }
2305 2306

      break;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2307
#endif
2308

Raymond Knopp's avatar
 
Raymond Knopp committed
2309 2310 2311
    case 'V':
      ouput_vcd = 1;
      break;
2312

Raymond Knopp's avatar
 
Raymond Knopp committed
2313
    case  'q':
Raymond Knopp's avatar
 
Raymond Knopp committed
2314 2315
      opp_enabled = 1;
      break;
2316

Raymond Knopp's avatar
 
Raymond Knopp committed
2317 2318 2319
    case  'R' :
      online_log_messages =1;
      break;
2320

Raymond Knopp's avatar
 
Raymond Knopp committed
2321
    case 'r':
2322
      UE_scan = 0;
2323

2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349
      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
2350
      }
2351

2352
      break;
2353

Raymond Knopp's avatar
 
Raymond Knopp committed
2354
    case 's':
2355
#if defined(OAI_USRP) || defined(CPRIGW)
Raymond Knopp's avatar
 
Raymond Knopp committed
2356 2357

      clock_src = atoi(optarg);
2358

Raymond Knopp's avatar
 
Raymond Knopp committed
2359
      if (clock_src == 0) {
2360 2361 2362 2363 2364
        //  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
2365
      }
2366

Raymond Knopp's avatar
 
Raymond Knopp committed
2367 2368 2369 2370
#else
      printf("Note: -s not defined for ExpressMIMO2\n");
#endif
      break;
2371

2372 2373 2374 2375
    case 'S':
      exit_missed_slots=0;
      printf("Skip exit for missed slots\n");
      break;
2376

2377
    case 'g':
Raymond Knopp's avatar
 
Raymond Knopp committed
2378
      glog_level=atoi(optarg); // value between 1 - 9
2379
      break;
2380 2381

    case 'F':
2382
#ifdef EXMIMO
2383 2384
      sprintf(rxg_fname,"%srxg.lime",optarg);
      rxg_fd = fopen(rxg_fname,"r");
2385

2386
      if (rxg_fd) {
2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404
        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);

2405
#endif
2406
      break;
2407

2408 2409 2410
    case 'G':
      glog_verbosity=atoi(optarg);// value from 0, 0x5, 0x15, 0x35, 0x75
      break;
2411

2412 2413
    case 'x':
      transmission_mode = atoi(optarg);
2414

2415
      if (transmission_mode > 2) {
2416 2417
        printf("Transmission mode > 2 (%d) not supported for the moment\n",transmission_mode);
        exit(-1);
2418
      }
2419
      break;
2420

2421 2422 2423
    case 'T':
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) 
	frame_parms[CC_id]->frame_type = TDD;
2424
      break;
2425

2426 2427 2428 2429
    case 'h':
      help ();
      exit (-1);
       
Raymond Knopp's avatar
 
Raymond Knopp committed
2430
    default:
2431 2432
      help ();
      exit (-1);
Raymond Knopp's avatar
 
Raymond Knopp committed
2433
      break;
2434 2435
    }
  }
2436

Raymond Knopp's avatar
 
Raymond Knopp committed
2437 2438
  if (UE_flag == 0)
    AssertFatal(conf_config_file_name != NULL,"Please provide a configuration file\n");
2439 2440


Raymond Knopp's avatar
 
Raymond Knopp committed
2441
  if ((UE_flag == 0) && (conf_config_file_name != NULL)) {
2442
    int i,j;
2443

Raymond Knopp's avatar
 
Raymond Knopp committed
2444
    NB_eNB_INST = 1;
2445

Raymond Knopp's avatar
 
Raymond Knopp committed
2446 2447
    /* Read eNB configuration file */
    enb_properties = enb_config_init(conf_config_file_name);
2448

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

Raymond Knopp's avatar
 
Raymond Knopp committed
2453
    /* Update some simulation parameters */
2454
    for (i=0; i < enb_properties->number; i++) {
2455
      AssertFatal (MAX_NUM_CCs == enb_properties->properties[i]->nb_cc,
2456 2457 2458
                   "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);

2459 2460
      for (j=0; j<enb_properties->properties[i]->nb_rrh_gw; j++) {
	
2461 2462 2463 2464 2465
	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));
	 
2466 2467 2468 2469 2470 2471 2472
	  printf( "\n\tRRH GW %d config for eNB %u:\n\n", j, i);
	  printf( "\tinterface name :       \t%s:\n",enb_properties->properties[i]->rrh_gw_if_name);
	  printf( "\tlocal address  :       \t%s:\n",enb_properties->properties[i]->rrh_gw_config[j].local_address);
	  printf( "\tlocal port     :       \t%d:\n",enb_properties->properties[i]->rrh_gw_config[j].local_port);
	  printf( "\tremote address :       \t%s:\n",enb_properties->properties[i]->rrh_gw_config[j].remote_address);
	  printf( "\tremote port    :       \t%d:\n",enb_properties->properties[i]->rrh_gw_config[j].remote_port);
	  printf( "\ttransport      :       \t%s Ethernet:\n\n",(enb_properties->properties[i]->rrh_gw_config[j].raw == 1)? "RAW" : "UDP");
2473 2474 2475 2476 2477 2478 2479 2480 2481 2482
	  
	  eth_params->local_if_name             = enb_properties->properties[i]->rrh_gw_if_name;
	  eth_params->my_addr                   = enb_properties->properties[i]->rrh_gw_config[j].local_address;
	  eth_params->my_port                   = enb_properties->properties[i]->rrh_gw_config[j].local_port;
	  eth_params->remote_addr               = enb_properties->properties[i]->rrh_gw_config[j].remote_address;
	  eth_params->remote_port               = enb_properties->properties[i]->rrh_gw_config[j].remote_port;
	  eth_params->transp_preference         = enb_properties->properties[i]->rrh_gw_config[j].raw;
 
	} else {
	  local_remote_radio = BBU_LOCAL_RADIO_HEAD; 
2483 2484 2485 2486
	}
	
      }

2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500
      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
2501 2502
      }

2503

2504
#ifdef OPENAIR2
2505

2506 2507 2508
      init_all_otg(0);
      g_otg->seed = 0;
      init_seeds(g_otg->seed);
2509 2510 2511 2512 2513 2514 2515 2516 2517 2518

      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");
2519
      }
2520

2521
      init_predef_traffic(enb_properties->properties[i]->num_otg_elements, 1);
2522

2523
#endif
2524

2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538
      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
2539 2540 2541 2542 2543 2544
# 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
2545 2546 2547
#if defined (ENABLE_SECURITY)
      osa_log_level                  = enb_properties->properties[i]->osa_log_level;
      osa_log_verbosity              = enb_properties->properties[i]->osa_log_verbosity;
2548
#endif
Florian Kaltenberger's avatar
Florian Kaltenberger committed
2549

Raymond Knopp's avatar
 
Raymond Knopp committed
2550
      // adjust the log
2551
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
2552 2553 2554 2555 2556 2557 2558 2559 2560 2561
        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
2562
      } // CC_id
2563
    }// i
2564 2565 2566 2567 2568 2569 2570 2571
  } 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
2572
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
2573
}
2574

2575 2576
int main( int argc, char **argv )
{
2577
  int i,aa,card=0;
Lionel Gauthier's avatar
Lionel Gauthier committed
2578
#if defined (XFORMS) || defined (EMOS) || defined (EXMIMO)
Raymond Knopp's avatar
 
Raymond Knopp committed
2579
  void *status;
2580
#endif
2581

Raymond Knopp's avatar
 
Raymond Knopp committed
2582
  int CC_id;
Raymond Knopp's avatar
 
Raymond Knopp committed
2583
  uint16_t Nid_cell = 0;
2584
  uint8_t  cooperation_flag=0,  abstraction_flag=0;
2585
#ifndef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
2586
  uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2;
2587 2588 2589
#endif

#ifdef ENABLE_TCXO
Raymond Knopp's avatar
 
Raymond Knopp committed
2590
  unsigned int tcxo = 114;
2591 2592
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
2593
#if defined (XFORMS)
2594 2595
  int ret;
#endif
2596
#if defined (EMOS) || (! defined (RTAI))
Raymond Knopp's avatar
 
Raymond Knopp committed
2597
  int error_code;
2598
#endif
2599

2600 2601 2602 2603 2604
#ifdef DEBUG_CONSOLE
  setvbuf(stdout, NULL, _IONBF, 0);
  setvbuf(stderr, NULL, _IONBF, 0);
#endif

2605 2606 2607
  PHY_VARS_UE *UE[MAX_NUM_CCs];

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

2610
  memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
Raymond Knopp's avatar
 
Raymond Knopp committed
2611
  set_latency_target();
2612

2613
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2614 2615
    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 */
2616
    frame_parms[CC_id]->frame_type          = FDD;
Raymond Knopp's avatar
 
Raymond Knopp committed
2617 2618
    frame_parms[CC_id]->tdd_config          = 3;
    frame_parms[CC_id]->tdd_config_S        = 0;
2619 2620
    frame_parms[CC_id]->N_RB_DL             = 100;
    frame_parms[CC_id]->N_RB_UL             = 100;
Raymond Knopp's avatar
 
Raymond Knopp committed
2621
    frame_parms[CC_id]->Ncp                 = NORMAL;
Raymond Knopp's avatar
 
Raymond Knopp committed
2622 2623
    frame_parms[CC_id]->Ncp_UL              = NORMAL;
    frame_parms[CC_id]->Nid_cell            = Nid_cell;
Raymond Knopp's avatar
 
Raymond Knopp committed
2624
    frame_parms[CC_id]->num_MBSFN_config    = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2625 2626 2627
    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
2628
  }
2629

2630 2631 2632 2633 2634
  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];
2635
    //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
2636
  }
2637 2638
  logInit();
 
2639
  rf_config_file[0]='\0';
2640
  get_options (argc, argv); //Command-line options
2641 2642 2643 2644
  if (rf_config_file[0] == '\0')
    openair0_cfg[0].configFilename = NULL;
  else
    openair0_cfg[0].configFilename = rf_config_file;
2645 2646
  
  // initialize the log (see log.h for details)
Florian Kaltenberger's avatar
Florian Kaltenberger committed
2647 2648
  set_glog(glog_level, glog_verbosity);

2649 2650
  //randominit (0);
  set_taus_seed (0);
Raymond Knopp's avatar
 
Raymond Knopp committed
2651

2652 2653
  if (UE_flag==1) {
    printf("configuring for UE\n");
2654

2655
    set_comp_log(HW,      LOG_INFO,  LOG_HIGH, 1);
2656 2657 2658 2659 2660 2661
    set_comp_log(PHY,     LOG_INFO,   LOG_HIGH, 1);
    set_comp_log(MAC,     LOG_INFO,   LOG_HIGH, 1);
    set_comp_log(RLC,     LOG_INFO,   LOG_HIGH, 1);
    set_comp_log(PDCP,    LOG_INFO,   LOG_HIGH, 1);
    set_comp_log(OTG,     LOG_INFO,   LOG_HIGH, 1);
    set_comp_log(RRC,     LOG_INFO,   LOG_HIGH, 1);
2662
#if defined(ENABLE_ITTI)
2663
    set_comp_log(EMU,     LOG_INFO,   LOG_MED, 1);
2664
# if defined(ENABLE_USE_MME)
2665
    set_comp_log(NAS,     LOG_INFO,   LOG_HIGH, 1);
2666 2667
# endif
#endif
2668 2669
  } else {
    printf("configuring for eNB\n");
2670

2671
    set_comp_log(HW,      hw_log_level, hw_log_verbosity, 1);
2672
#ifdef OPENAIR2
2673 2674 2675 2676 2677
    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);

2678
#else
2679
    set_comp_log(PHY,     LOG_INFO,   LOG_HIGH, 1);
2680
#endif
2681 2682 2683 2684
    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);
2685
#if defined(ENABLE_ITTI)
2686
    set_comp_log(EMU,     LOG_INFO,   LOG_MED, 1);
2687
# if defined(ENABLE_USE_MME)
2688 2689 2690 2691
    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);
2692
# endif
2693
#if defined(ENABLE_SECURITY)
2694
    set_comp_log(OSA,    osa_log_level,   osa_log_verbosity, 1);
2695
#endif
2696
#endif
2697
#ifdef LOCALIZATION
2698 2699 2700 2701 2702 2703 2704 2705 2706
    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
2707
    }
2708
  }
2709

Raymond Knopp's avatar
 
Raymond Knopp committed
2710 2711
  if (ouput_vcd) {
    if (UE_flag==1)
2712
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_UE.vcd");
Raymond Knopp's avatar
 
Raymond Knopp committed
2713
    else
2714
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_eNB.vcd");
Raymond Knopp's avatar
 
Raymond Knopp committed
2715
  }
2716

2717
  if (opp_enabled ==1){
2718
    reset_opp_meas();
2719 2720
  }
  cpuf=get_cpu_freq_GHz();
2721

2722
#if defined(ENABLE_ITTI)
2723

Raymond Knopp's avatar
 
Raymond Knopp committed
2724 2725
  if (UE_flag == 1) {
    log_set_instance_type (LOG_INSTANCE_UE);
2726
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
2727 2728
    log_set_instance_type (LOG_INSTANCE_ENB);
  }
2729

Raymond Knopp's avatar
 
Raymond Knopp committed
2730
  itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, itti_dump_file);
2731
 
2732 2733
  // initialize mscgen log after ITTI
  MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX);
2734 2735
#endif
 
2736
#ifdef OPENAIR2
2737

2738 2739
  if (opt_type != OPT_NONE) {
    radio_type_t radio_type;
2740

2741 2742
    if (frame_parms[0]->frame_type == FDD)
      radio_type = RADIO_TYPE_FDD;
2743
    else
2744
      radio_type = RADIO_TYPE_TDD;
2745

2746 2747 2748
    if (init_opt(in_path, in_ip, NULL, radio_type) == -1)
      LOG_E(OPT,"failed to run OPT \n");
  }
2749

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

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

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

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

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


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

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

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

    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
2816 2817 2818 2819

      PHY_vars_UE_g[0][CC_id] = init_lte_UE(frame_parms[CC_id], 0,abstraction_flag,transmission_mode);
      UE[CC_id] = PHY_vars_UE_g[0][CC_id];
      printf("PHY_vars_UE_g[0][%d] = %p\n",CC_id,UE[CC_id]);
Raymond Knopp's avatar
 
Raymond Knopp committed
2820
#ifndef OPENAIR2
2821 2822 2823 2824 2825 2826 2827 2828 2829

      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
2830
      }
2831

2832
#endif
2833 2834 2835


      UE[CC_id]->UE_scan = UE_scan;
2836
      UE[CC_id]->UE_scan_carrier = UE_scan_carrier;
2837 2838 2839
      UE[CC_id]->mode    = mode;

      compute_prach_seq(&UE[CC_id]->lte_frame_parms.prach_config_common,
2840 2841 2842
                        UE[CC_id]->lte_frame_parms.frame_type,
                        UE[CC_id]->X_u);

2843
      UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1234;
2844
#ifndef OPENAIR2
2845
      UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1235;
2846
#endif
2847

2848
#ifdef EXMIMO
2849

2850 2851 2852 2853
      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
2854
      }
2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873

      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
2874
      }
2875

2876
#else
2877
      UE[CC_id]->rx_total_gain_dB =  (int)rx_gain[CC_id][0];
2878
#endif
2879

2880
      UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id];
2881

2882 2883


2884
#ifdef EXMIMO
2885

Raymond Knopp's avatar
 
Raymond Knopp committed
2886
      //N_TA_offset
2887
      if (UE[CC_id]->lte_frame_parms.frame_type == TDD) {
2888 2889 2890 2891 2892 2893 2894 2895
        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
2896
      }
2897

2898
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
2899
      //already taken care of in lte-softmodem
2900
      UE[CC_id]->N_TA_offset = 0;
2901
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2902
    }
2903

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



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

2921
#ifndef OPENAIR2
2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937

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

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

#endif

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

2939
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
2940

2941
      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
2942

2943
#else
2944 2945 2946
      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
2947

2948 2949 2950
      // 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
2951

2952
#endif
2953

2954
#ifdef EXMIMO
2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965

      //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
2966
      }
2967

2968
#else
2969
      //already taken care of in lte-softmodem.c
2970 2971
      PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 0;
#endif
2972

2973
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
2974 2975


2976 2977 2978 2979 2980 2981 2982 2983 2984
    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;

  }
2985 2986 2987 2988
#ifndef RTAI
  fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx);
  cpuf=get_cpu_freq_GHz();
#endif 
2989

Raymond Knopp's avatar
 
Raymond Knopp committed
2990
  dump_frame_parms(frame_parms[0]);
2991

2992 2993 2994
  for (card=0; card<MAX_CARDS; card++) {

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

    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
3029

3030 3031 3032 3033 3034 3035
    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;    
    }
3036

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

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

3049
    openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL;
Raymond Knopp's avatar
 
Raymond Knopp committed
3050
#endif
3051

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

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

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

3078
#if 0  // UHD 3.8     
3079 3080
      switch(frame_parms[0]->N_RB_DL) {
      case 6:
3081
        openair0_cfg[card].rx_gain[i] -= 12;
3082 3083
        break;

3084
      case 25:
3085
        openair0_cfg[card].rx_gain[i] -= 6;
3086 3087
        break;

3088
      case 50:
3089 3090 3091 3092 3093
        openair0_cfg[card].rx_gain[i] -= 3;
        break;

      case 100:
        openair0_cfg[card].rx_gain[i] -= 0;
3094 3095
        break;

3096
      default:
3097
        break;
3098
      }
3099
#endif      
3100

Raymond Knopp's avatar
 
Raymond Knopp committed
3101
    }
3102

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

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

  mac_xface = malloc(sizeof(MAC_xface));

3143
#ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
3144
  int eMBMS_active=0;
3145

Raymond Knopp's avatar
 
Raymond Knopp committed
3146
  l2_init(frame_parms[0],eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL,
3147 3148 3149 3150
          0,// cba_group_active
          0); // HO flag


3151 3152
#endif

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

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

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3173
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3174

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

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

3199

3200

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

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

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

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

3227 3228 3229 3230 3231 3232 3233
    if (input_fd) {
      printf("Reading in from file to antenna buffer %d\n",0);
      fread(UE[0]->lte_ue_common_vars.rxdata[0],
	    sizeof(int32_t),
	    frame_parms[0]->samples_per_tti*10,
	    input_fd);
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
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
#ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
3565
  //cleanup_pdcp_thread();
3566 3567
#endif

3568
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3569
  stop_rt_timer();
3570
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3571 3572
  pthread_cond_destroy(&sync_cond);
  pthread_mutex_destroy(&sync_mutex);
3573

3574

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3598
  if (ouput_vcd)
3599
    VCD_SIGNAL_DUMPER_CLOSE();
3600

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3601
#ifdef OPENAIR2
3602

3603
  if (opt_enabled == 1)
3604
    terminate_opt();
3605

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3606
#endif
3607

Raymond Knopp's avatar
 
Raymond Knopp committed
3608
  logClean();
3609

Raymond Knopp's avatar
 
Raymond Knopp committed
3610 3611
  return 0;
}
3612 3613


3614 3615 3616
/* 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
3617
   antennas are mapped to successive RF chains on the same card. */
3618 3619
int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs])
{
3620

3621
  int i, CC_id;
3622
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3623
  uint16_t N_TA_offset = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3624 3625
#else
  int j;
Raymond Knopp's avatar
 
Raymond Knopp committed
3626
#endif
3627
  LTE_DL_FRAME_PARMS *frame_parms;
3628

Raymond Knopp's avatar
 
Raymond Knopp committed
3629

3630 3631
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    if (phy_vars_eNB[CC_id]) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3632 3633
      frame_parms = &(phy_vars_eNB[CC_id]->lte_frame_parms);
      printf("setup_eNB_buffers: frame_parms = %p\n",frame_parms);
3634
    } else {
3635 3636
      printf("phy_vars_eNB[%d] not initialized\n", CC_id);
      return(-1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3637
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3638

3639
#ifndef EXMIMO
3640

3641 3642
    if (frame_parms->frame_type == TDD) {
      if (frame_parms->N_RB_DL == 100)
3643
        N_TA_offset = 624;
3644
      else if (frame_parms->N_RB_DL == 50)
3645
        N_TA_offset = 624/2;
3646
      else if (frame_parms->N_RB_DL == 25)
3647
        N_TA_offset = 624/4;
Raymond Knopp's avatar
 
Raymond Knopp committed
3648
    }
3649

Raymond Knopp's avatar
 
Raymond Knopp committed
3650
#endif
3651

Raymond Knopp's avatar
 
Raymond Knopp committed
3652
    // replace RX signal buffers with mmaped HW versions
3653
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3654 3655 3656
    openair0_cfg[CC_id].tx_num_channels = 0;
    openair0_cfg[CC_id].rx_num_channels = 0;

3657
    for (i=0; i<frame_parms->nb_antennas_rx; i++) {
3658 3659 3660
      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];
3661

3662
      if (openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i]) {
3663 3664 3665 3666 3667 3668
        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++;
3669
      }
3670

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

      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;
3676
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
3677
    }
3678 3679

    for (i=0; i<frame_parms->nb_antennas_tx; i++) {
3680 3681 3682
      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];
3683

3684
      if (openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i]) {
3685 3686 3687 3688 3689 3690
        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++;
3691
      }
3692

3693
      printf("txdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3694 3695 3696 3697

      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;
3698
      }
3699
    }
3700

3701
#else // not EXMIMO
3702 3703 3704
    rxdata = (int32_t**)malloc16(frame_parms->nb_antennas_rx*sizeof(int32_t*));
    txdata = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*));

3705
    for (i=0; i<frame_parms->nb_antennas_rx; i++) {
3706
      free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]);
3707
      rxdata[i] = (int32_t*)(32 + malloc16(32+openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation
3708
      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
3709
      memset(rxdata[i], 0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t));
3710
      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);
3711
      
Raymond Knopp's avatar
 
Raymond Knopp committed
3712
    }
3713 3714

    for (i=0; i<frame_parms->nb_antennas_tx; i++) {
3715
      free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3716
      txdata[i] = (int32_t*)(32 + malloc16(32 + openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation
3717
      phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i] = txdata[i];
3718
      memset(txdata[i],0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t));
3719
      printf("txdata[%d] @ %p\n", i, phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3720

Raymond Knopp's avatar
 
Raymond Knopp committed
3721
    }
3722

Raymond Knopp's avatar
 
Raymond Knopp committed
3723
#endif
3724
  }
3725

3726
  return(0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3727
}
3728

3729
void reset_opp_meas(void) {
3730 3731 3732
  int sfn;
  reset_meas(&softmodem_stats_mt);
  reset_meas(&softmodem_stats_hw);
3733
  
3734 3735 3736 3737 3738 3739
  for (sfn=0; sfn < 10; sfn++) {
    reset_meas(&softmodem_stats_tx_sf[sfn]);
    reset_meas(&softmodem_stats_rx_sf[sfn]);
  }
}

3740 3741
void print_opp_meas(void) {

3742 3743 3744
  int sfn=0;
  print_meas(&softmodem_stats_mt, "Main ENB Thread", NULL, NULL);
  print_meas(&softmodem_stats_hw, "HW Acquisation", NULL, NULL);
3745
  
3746 3747 3748 3749 3750
  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);
  }
}
3751 3752