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

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


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

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

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

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

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

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

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

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

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

#include "PHY/types.h"
66

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

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

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

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

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

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

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

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

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

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

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

#define FRAME_PERIOD    100000000ULL
#define DAQ_PERIOD      66667ULL

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

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

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


Raymond Knopp's avatar
 
Raymond Knopp committed
147

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

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

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

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

#ifdef RTAI
171

172 173
static long                      main_eNB_thread;
static long                      main_ue_thread;
174

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

179
pthread_attr_t                  attr_dlsch_threads;
180 181
pthread_attr_t                  attr_UE_thread;

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

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

191

192 193


194
struct sched_param              sched_param_UE_thread;
195

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
212

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

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

223

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
234

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

238
static char                     threequarter_fs=0;
239

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

243
openair0_rf_map rf_map[MAX_NUM_CCs];
244

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

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

254 255
FILE *input_fd=NULL;

256

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

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

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

293 294
char   rf_config_file[1024];

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

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

#endif
303 304

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
327

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

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

Lionel Gauthier's avatar
 
Lionel Gauthier committed
353 354 355 356 357 358
# if defined(ENABLE_USE_MME)
int16_t           gtpu_log_level     = LOG_DEBUG;
int16_t           gtpu_log_verbosity = LOG_MED;
int16_t           udp_log_level      = LOG_DEBUG;
int16_t           udp_log_verbosity  = LOG_MED;
#endif
359 360 361
#if defined (ENABLE_SECURITY)
int16_t           osa_log_level      = LOG_INFO;
int16_t           osa_log_verbosity  = LOG_MED;
362
#endif
363

Raymond Knopp's avatar
 
Raymond Knopp committed
364 365

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

/* flag set by eNB conf file to specify if the radio head is local or remote (default option is local) */
uint8_t local_remote_radio = BBU_LOCAL_RADIO_HEAD;
/* struct for ethernet specific parameters given in eNB conf file */
eth_params_t *eth_params;

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

379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
/*---------------------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;
}

Cedric Roux's avatar
Cedric Roux committed
397
void print_difftimes(void)
398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
{
#ifdef DEBUG
    printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
#else
    LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
#endif
}

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

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

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

429
#if !defined(ENABLE_ITTI)
430 431 432 433 434 435 436 437
void signal_handler(int sig)
{
  void *array[10];
  size_t size;

  if (sig==SIGSEGV) {
    // get void*'s for all entries on the stack
    size = backtrace(array, 10);
438

439 440 441 442
    // print out all the frames to stderr
    fprintf(stderr, "Error: signal %d:\n", sig);
    backtrace_symbols_fd(array, size, 2);
    exit(-1);
443 444
  } else {
    printf("trying to exit gracefully...\n");
445
    oai_exit = 1;
446 447
  }
}
448
#endif
449 450 451 452 453 454 455 456 457 458 459
#define KNRM  "\x1B[0m"
#define KRED  "\x1B[31m"
#define KGRN  "\x1B[32m"
#define KBLU  "\x1B[34m"
#define RESET "\033[0m"

void help (void) {
  printf (KGRN "Usage:\n");
  printf("  sudo -E lte-softmodem [options]\n");
  printf("  sudo -E ./lte-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.openEPC.conf -S -V -m 26 -t 16 -x 1 --ulsch-max-errors 100 -W\n\n");
  printf("Options:\n");
460
  printf("  --rf-config-file Configuration file for front-end (e.g. LMS7002M)\n");
461 462 463 464
  printf("  --ulsch-max-errors set the max ULSCH erros\n");
  printf("  --calib-ue-rx set UE RX calibration\n");
  printf("  --calib-ue-rx-med \n");
  printf("  --calib-ue-rxbyp\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
465 466
  printf("  --debug-ue-prach run normal prach power ramping, but don't continue random-access\n");
  printf("  --calib-prach-tx run normal prach with maximum power, but don't continue random-access\n");
467
  printf("  --no-L2-connect bypass L2 and upper layers\n");
468 469 470 471
  printf("  --ue-rxgain set UE RX gain\n");
  printf("  --ue-txgain set UE TX gain\n");
  printf("  --ue-scan_carrier set UE to scan around carrier\n");
  printf("  --loop-memory get softmodem (UE) to loop through memory instead of acquiring from HW\n");
472
  printf("  -C Set the downlink frequency for all component carriers\n");
473 474 475
  printf("  -d Enable soft scope and L1 and L2 stats (Xforms)\n");
  printf("  -F Calibrate the EXMIMO borad, available files: exmimo2_2arxg.lime exmimo2_2brxg.lime \n");
  printf("  -g Set the global log level, valide options: (9:trace, 8/7:debug, 6:info, 4:warn, 3:error)\n");
476
  printf("  -G Set the global log verbosity \n");
477 478 479 480 481
  printf("  -h provides this help message!\n");
  printf("  -K Generate ITTI analyzser logs (similar to wireshark logs but with more details)\n");
  printf("  -m Set the maximum downlink MCS\n");
  printf("  -O eNB configuration file (located in targets/PROJECTS/GENERIC-LTE-EPC/CONF\n");
  printf("  -q Enable processing timing measurement of lte softmodem on per subframe basis \n");
kaltenbe's avatar
kaltenbe committed
482
  printf("  -r Set the PRB, valid values: 6, 25, 50, 100  \n");    
483 484
  printf("  -S Skip the missed slots/subframes \n");    
  printf("  -t Set the maximum uplink MCS\n");
485
  printf("  -T Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n");
486 487 488 489
  printf("  -U Set the lte softmodem as a UE\n");
  printf("  -W Enable L2 wireshark messages on localhost \n");
  printf("  -V Enable VCD (generated file will be located atopenair_dump_eNB.vcd, read it with target/RT/USER/eNB.gtkw\n");
  printf("  -x Set the transmission mode, valid options: 1 \n"RESET);    
490

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

  oai_exit = 1;

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

  //rt_sleep_ns(FRAME_PERIOD);

  //exit (-1);
}

510

511
#ifdef XFORMS
512

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

  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    for (k=0; k<8; k++) { //harq_processes
      for (j=0; j<phy_vars_eNB->dlsch_eNB[i][0]->Mdlharq; j++) {
        phy_vars_eNB->eNB_UE_stats[i].dlsch_NAK[k][j]=0;
        phy_vars_eNB->eNB_UE_stats[i].dlsch_ACK[k][j]=0;
        phy_vars_eNB->eNB_UE_stats[i].dlsch_trials[k][j]=0;
524
      }
525

526 527 528
      phy_vars_eNB->eNB_UE_stats[i].dlsch_l2_errors[k]=0;
      phy_vars_eNB->eNB_UE_stats[i].ulsch_errors[k]=0;
      phy_vars_eNB->eNB_UE_stats[i].ulsch_consecutive_errors=0;
529 530 531 532 533 534

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

538 539 540
    phy_vars_eNB->eNB_UE_stats[i].dlsch_sliding_cnt=0;
    phy_vars_eNB->eNB_UE_stats[i].dlsch_NAK_round0=0;
    phy_vars_eNB->eNB_UE_stats[i].dlsch_mcs_offset=0;
541 542 543
  }
}

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

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

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

559
# ifdef ENABLE_XFORMS_WRITE_STATS
560 561

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

566
#endif
567

Raymond Knopp's avatar
 
Raymond Knopp committed
568 569
  while (!oai_exit) {
    if (UE_flag==1) {
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
570
      len = dump_ue_stats (PHY_vars_UE_g[0][0], stats_buffer, 0, mode,rx_input_level_dBm);
knopp's avatar
knopp committed
571 572 573
      //fl_set_object_label(form_stats->stats_text, stats_buffer);
      fl_clear_browser(form_stats->stats_text);
      fl_add_browser_line(form_stats->stats_text, stats_buffer);
574

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

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

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

592 593 594
      //fl_set_object_label(form_stats->stats_text, stats_buffer);
      fl_clear_browser(form_stats->stats_text);
      fl_add_browser_line(form_stats->stats_text, stats_buffer);
595

596
      for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
597 598 599 600 601
	for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
	  phy_scope_eNB(form_enb[CC_id][UE_id],
			PHY_vars_eNB_g[0][CC_id],
			UE_id);
	}
Raymond Knopp's avatar
 
Raymond Knopp committed
602
      }
603

604
    }
605

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

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

613
# ifdef ENABLE_XFORMS_WRITE_STATS
614

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

629
# endif
630

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

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

jiangx's avatar
jiangx committed
638 639 640 641 642 643 644 645
void* gps_thread (void *arg)
{

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

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

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

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

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

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

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

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

678 679 680

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

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

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

    //rt_sleep_ns(1000000000LL);
    sleep(1);
  } //oai_exit
jiangx's avatar
jiangx committed
703 704 705 706 707

  pthread_exit((void*) arg);

}

708 709 710 711 712 713 714 715 716 717 718
void *emos_thread (void *arg)
{
  char c;
  char *fifo2file_buffer, *fifo2file_ptr;

  int fifo, counter=0, bytes;

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

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

722 723 724
  time_t timer;
  struct tm *now;

725
  struct sched_param sched_param;
726 727

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

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

732 733 734 735 736 737 738 739 740 741 742 743
  timer = time(NULL);
  now = localtime(&timer);

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

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

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

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


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

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

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


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

771 772 773 774 775 776 777
  while (!oai_exit) {
    /*
    bytes = rtf_read_timed(fifo, fifo2file_ptr, channel_buffer_size,100);
    if (bytes==0)
    continue;
    */
    bytes = rtf_read_all_at_once(fifo, fifo2file_ptr, channel_buffer_size);
778

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

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

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

795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815
    fifo2file_ptr += channel_buffer_size;
    counter ++;

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

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


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

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

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

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

}
#endif

833 834


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

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

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

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

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
865

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

875 876 877
      itti_receive_msg (TASK_L2L1, &message_p);

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

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

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

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

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

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

    case ACTIVATE_MESSAGE:
      start_UE = 1;
      break;

    case DEACTIVATE_MESSAGE:
      start_UE = 0;
      break;
917

Raymond Knopp's avatar
 
Raymond Knopp committed
918 919 920 921 922 923 924 925 926 927 928
    case MESSAGE_TEST:
      LOG_I(EMU, "Received %s\n", ITTI_MSG_NAME(message_p));
      break;

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
935

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

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

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
954

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

982 983 984 985 986
      // if S-subframe generate first slot only
      if (subframe_select(&phy_vars_eNB->lte_frame_parms,subframe) == SF_S)
	len = phy_vars_eNB->lte_frame_parms.samples_per_tti>>1;
      else
	len = phy_vars_eNB->lte_frame_parms.samples_per_tti;
kaltenbe's avatar
kaltenbe committed
987
      /*
988 989 990 991 992
      for (i=0;i<len;i+=4) {
	dummy_tx_b[i] = 0x100;
	dummy_tx_b[i+1] = 0x01000000;
	dummy_tx_b[i+2] = 0xff00;
	dummy_tx_b[i+3] = 0xff000000;
kaltenbe's avatar
kaltenbe committed
993
	}*/
994
      for (i=0; i<len; i++) {
995 996
        tx_offset = (int)slot_offset+time_offset[aa]+i;

997
	
998 999 1000 1001 1002 1003
        if (tx_offset<0)
          tx_offset += LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti;

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

1004 1005 1006
	((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[0] = ((short*)dummy_tx_b)[2*i]<<openair0_cfg[0].iq_txshift;
	
	((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[1] = ((short*)dummy_tx_b)[2*i+1]<<openair0_cfg[0].iq_txshift;
1007 1008 1009 1010 1011 1012 1013
     }
     // if S-subframe switch to RX in second subframe
     if (subframe_select(&phy_vars_eNB->lte_frame_parms,subframe) == SF_S) {
       for (i=0; i<len; i++) {
	 phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset++] = 0x00010001;
       }
     }
1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032

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

1037 1038 1039 1040 1041 1042 1043 1044 1045
/* mutex, cond and variable to serialize phy proc TX calls
 * (this mechanism may be relaxed in the future for better
 * performances)
 */
static struct {
  pthread_mutex_t  mutex_phy_proc_tx;
  pthread_cond_t   cond_phy_proc_tx;
  volatile uint8_t phy_proc_CC_id;
} sync_phy_proc[NUM_ENB_THREADS];
Raymond Knopp's avatar
 
Raymond Knopp committed
1046

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

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

1061 1062 1063 1064
  if (opp_enabled == 1) {
    snprintf(tx_time_name, 100,"/tmp/%s_tx_time_thread_sf_%d", "eNB", proc->subframe);
    tx_time_file = fopen(tx_time_name,"w");
  }
1065 1066 1067
  // set default return value
  eNB_thread_tx_status[proc->subframe] = 0;

1068 1069
  MSC_START_USE();

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

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

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

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

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

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

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

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

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

  mlockall(MCL_CURRENT | MCL_FUTURE);

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

1127
  while (!oai_exit) {
1128

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

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

1137
    while (proc->instance_cnt_tx < 0) {
1138 1139 1140
      // most of the time the thread is waiting here
      // proc->instance_cnt_tx is -1
      pthread_cond_wait( &proc->cond_tx, &proc->mutex_tx ); // this unlocks mutex_tx while waiting and then locks it again
1141
    }
1142

1143 1144 1145 1146 1147
    if (pthread_mutex_unlock(&proc->mutex_tx) != 0) {
      LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for eNB TX proc %d\n",proc->subframe);
      exit_fun("nothing to add");
      break;
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1148

1149 1150
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe), 1 );
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX_ENB, proc->frame_tx );
1151 1152 1153
    start_meas( &softmodem_stats_tx_sf[proc->subframe] );

    if (oai_exit) break;
1154

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

1173 1174 1175
      if (pthread_mutex_unlock(&sync_phy_proc[proc->subframe].mutex_phy_proc_tx) != 0) {
        LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc %d\n", proc->subframe);
        exit_fun("nothing to add");
1176 1177
      }

1178 1179 1180
      if (oai_exit)
        break;

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

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

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

1220 1221 1222 1223 1224 1225 1226 1227 1228
    proc->instance_cnt_tx--;

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

    proc->frame_tx++;
1229

1230 1231
    if (proc->frame_tx==1024)
      proc->frame_tx=0;
1232
    stop_meas( &softmodem_stats_tx_sf[proc->subframe] );
1233 1234 1235 1236 1237 1238 1239
#ifdef LOWLATENCY
    if (opp_enabled){
      if(softmodem_stats_tx_sf[proc->subframe].diff_now/(cpuf) > attr.sched_runtime){
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_TX_ENB, (softmodem_stats_tx_sf[proc->subframe].diff_now/cpuf - attr.sched_runtime)/1000000.0);
      }
    }
#endif 
1240 1241
    print_meas_now(&softmodem_stats_tx_sf[proc->subframe],"eNB_TX_SF",proc->subframe, tx_time_file);

1242 1243
  }

1244 1245


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

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

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

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


1265 1266 1267 1268 1269 1270 1271 1272 1273 1274
/*!
 * \brief The receive thread of eNB.
 * \ref NUM_ENB_THREADS threads of this type are active at the same time.
 * \param param is a \ref eNB_proc_t structure which contains the info what to process.
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
static void* eNB_thread_rx( void* param )
{
  static int eNB_thread_rx_status[NUM_ENB_THREADS];

Raymond Knopp's avatar
 
Raymond Knopp committed
1275
  eNB_proc_t *proc = (eNB_proc_t*)param;
1276

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

1281 1282 1283 1284
  if (opp_enabled == 1){
    snprintf(rx_time_name, 100,"/tmp/%s_rx_time_thread_sf_%d", "eNB", proc->subframe);
    rx_time_file = fopen(rx_time_name,"w");
  }
1285 1286 1287
  // set default return value
  eNB_thread_rx_status[proc->subframe] = 0;

1288 1289
  MSC_START_USE();

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

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

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

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

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

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

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

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

  mlockall(MCL_CURRENT | MCL_FUTURE);

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1351
    if (pthread_mutex_lock(&proc->mutex_rx) != 0) {
1352 1353 1354
      LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB RX proc %d\n", proc->subframe );
      exit_fun( "error locking mutex" );
      break;
Raymond Knopp's avatar
 
Raymond Knopp committed
1355 1356
    }

1357
    while (proc->instance_cnt_rx < 0) {
1358 1359 1360
      // most of the time the thread is waiting here
      // proc->instance_cnt_rx is -1
      pthread_cond_wait( &proc->cond_rx, &proc->mutex_rx ); // this unlocks mutex_rx while waiting and then locks it again
Raymond Knopp's avatar
 
Raymond Knopp committed
1361
    }
1362 1363 1364 1365 1366 1367 1368

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

1369 1370
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 1 );
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx );
1371
    start_meas( &softmodem_stats_rx_sf[proc->subframe] );
1372

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

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1385
    if (pthread_mutex_lock(&proc->mutex_rx) != 0) {
1386 1387 1388
      LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB RX proc %d\n", proc->subframe );
      exit_fun( "error locking mutex" );
      break;
Raymond Knopp's avatar
 
Raymond Knopp committed
1389
    }
1390 1391 1392 1393 1394 1395 1396

    proc->instance_cnt_rx--;

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

    proc->frame_rx++;
1400

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

1404
    stop_meas( &softmodem_stats_rx_sf[proc->subframe] );
1405 1406 1407 1408 1409 1410 1411
#ifdef LOWLATENCY
    if (opp_enabled){
      if(softmodem_stats_rx_sf[proc->subframe].diff_now/(cpuf) > attr.sched_runtime){
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_RX_ENB, (softmodem_stats_rx_sf[proc->subframe].diff_now/cpuf - attr.sched_runtime)/1000000.0);
      }
    }
#endif  
1412
    print_meas_now(&softmodem_stats_rx_sf[proc->subframe],"eNB_RX_SF",proc->subframe, rx_time_file);
Raymond Knopp's avatar
 
Raymond Knopp committed
1413
  }
1414

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

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

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

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



Raymond Knopp's avatar
 
Raymond Knopp committed
1436

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

1442 1443 1444
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    for (i=0; i<NUM_ENB_THREADS; i++) {
      // set the stack size
navid's avatar
navid committed
1445
     
1446

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


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

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

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

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

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

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

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

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

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

1548 1549 1550 1551 1552 1553 1554 1555 1556
      if (result != 0) {
        printf( "Error joining thread.\n" );
      } else {
        if (status) {
          printf( "status %d\n", *status );
        } else {
          printf( "The thread was killed. No status available.\n" );
        }
      }
1557

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

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

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

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

1574 1575
#ifdef DEBUG_THREADS

1576 1577 1578 1579 1580 1581 1582 1583 1584
      if (result != 0) {
        printf( "Error joining thread.\n" );
      } else {
        if (status) {
          printf( "status %d\n", *status );
        } else {
          printf( "The thread was killed. No status available.\n" );
        }
      }
1585

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

      pthread_mutex_destroy( &PHY_vars_eNB_g[0][CC_id]->proc[i].mutex_tx );
      pthread_mutex_destroy( &PHY_vars_eNB_g[0][CC_id]->proc[i].mutex_rx );
      pthread_cond_destroy( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_tx );
      pthread_cond_destroy( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_rx );
Raymond Knopp's avatar
 
Raymond Knopp committed
1594
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1595 1596 1597
}


Raymond Knopp's avatar
 
Raymond Knopp committed
1598 1599


1600

Raymond Knopp's avatar
 
Raymond Knopp committed
1601

1602 1603 1604 1605 1606 1607
/*!
 * \brief This is the main eNB thread.
 * \param arg unused
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
static void* eNB_thread( void* arg )
1608
{
1609 1610
  UNUSED(arg);
  static int eNB_thread_status;
1611

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

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

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

Cedric Roux's avatar
Cedric Roux committed
1641 1642 1643 1644 1645
  /* avoid gcc warnings */
  (void)trx_time0;
  (void)trx_time1;
  (void)trx_time2;

1646
#ifdef RTAI
1647
  RT_TASK* task = rt_task_init_schmod(nam2num("eNBmain"), 0, 0, 0, SCHED_FIFO, 0xF);
1648
#else
1649
#ifdef LOWLATENCY
1650 1651 1652
  struct sched_attr attr;
  unsigned int flags = 0;

Raymond Knopp's avatar
 
Raymond Knopp committed
1653 1654 1655 1656
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1657

1658
  /* This creates a .2 ms  reservation */
Raymond Knopp's avatar
 
Raymond Knopp committed
1659
  attr.sched_policy = SCHED_DEADLINE;
navid's avatar
navid committed
1660
  attr.sched_runtime  = (0.3 * 100) * 10000;
1661 1662
  attr.sched_deadline = (0.9 * 100) * 10000;
  attr.sched_period   = 1 * 1000000;
1663

Lionel Gauthier's avatar
Lionel Gauthier committed
1664

Raymond Knopp's avatar
 
Raymond Knopp committed
1665 1666 1667 1668
  /* 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");
     }*/
1669

1670
  if (sched_setattr(0, &attr, flags) < 0 ) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1671 1672 1673 1674
    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",
1675
          gettid(),sched_getcpu());
Raymond Knopp's avatar
 
Raymond Knopp committed
1676
  }
1677

1678
#endif
1679 1680
#endif

1681 1682 1683 1684 1685
  // stop early, if an exit is requested
  // FIXME really neccessary?
  if (oai_exit)
    goto eNB_thread_cleanup;

1686
#ifdef RTAI
1687
  printf( "[SCHED][eNB] Started eNB main thread (id %p)\n", task );
Raymond Knopp's avatar
 
Raymond Knopp committed
1688
#else
Cedric Roux's avatar
Cedric Roux committed
1689
  printf( "[SCHED][eNB] Started eNB main thread on CPU %d TID %ld\n", sched_getcpu(), gettid());
1690 1691 1692
#endif

#ifdef HARD_RT
1693
  rt_make_hard_real_time();
1694 1695
#endif

1696 1697 1698 1699 1700 1701 1702 1703
  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;
1704

1705 1706
  printf( "waiting for sync (eNB_thread)\n" );
  pthread_mutex_lock( &sync_mutex );
1707

1708 1709
  while (sync_var<0)
    pthread_cond_wait( &sync_cond, &sync_mutex );
1710

1711
  pthread_mutex_unlock(&sync_mutex);
1712

1713 1714
  printf( "got sync (eNB_thread)\n" );

1715
  int frame = 0;
1716

1717
#ifndef EXMIMO
1718 1719
  spp        = openair0_cfg[0].samples_per_packet;
  tx_pos     = openair0_cfg[0].tx_scheduling_advance;
1720
#endif
1721

1722 1723 1724 1725
#if defined(ENABLE_ITTI)
  wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB);
#endif 

1726 1727
  while (!oai_exit) {
    start_meas( &softmodem_stats_mt );
Raymond Knopp's avatar
 
Raymond Knopp committed
1728

1729
#ifdef EXMIMO
1730 1731
    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]);
1732 1733
    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);
1734 1735 1736 1737
    //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];
1738

1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749
    //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;
1750

1751
      if (diff<0)
1752
        diff = diff + 150;
1753

1754 1755 1756 1757
      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)))) {
1758

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

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

    
1792
    }
1793

1794
    if (diff>8)
1795 1796
      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);
1797

1798 1799
    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);
1800 1801

    delay_cnt = 0;
1802

1803 1804 1805 1806
    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);
1807
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP,1);
1808
      ret = rt_sleep_ns(diff*DAQ_PERIOD);
1809 1810
      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);
1811

1812 1813
      if (ret)
        LOG_D(HW,"eNB Frame %d, time %llu: rt_sleep_ns returned %d\n",frame, time_in);
1814

Raymond Knopp's avatar
 
Raymond Knopp committed
1815
      hw_slot = (((((volatile unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15;
1816 1817 1818
      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());
1819
      delay_cnt++;
1820

1821 1822 1823 1824 1825
      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");
      }
1826

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1829
      if ((mbox_current>=135) && (mbox_target<15)) //handle the frame wrap-arround
1830
        diff = 150-mbox_current+mbox_target;
Raymond Knopp's avatar
 
Raymond Knopp committed
1831
      else if ((mbox_current<15) && (mbox_target>=135))
1832
        diff = -150+mbox_target-mbox_current;
Raymond Knopp's avatar
 
Raymond Knopp committed
1833
      else
1834 1835
        diff = mbox_target - mbox_current;
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1836

1837
#else  // EXMIMO
1838 1839
    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 );
1840
    tx_launched = 0;
1841

1842
    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
1843

1844
      unsigned int rxs;
Raymond Knopp's avatar
 
Raymond Knopp committed
1845
#ifndef USRP_DEBUG
1846 1847 1848
      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
1849

1850
      clock_gettime( CLOCK_MONOTONIC, &trx_time0 );
1851

1852
       start_meas( &softmodem_stats_hw );
1853

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

navid's avatar
navid committed
1872
      if (frame > 20){ 
1873 1874 1875
	if (rxs != spp)
	  exit_fun( "problem receiving samples" );
      }
1876
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
1877

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

      stop_meas( &softmodem_stats_mt );
1898 1899
      if (frame > 50) { 
	  clock_gettime( CLOCK_MONOTONIC, &trx_time2 );
Aikaterini's avatar
Aikaterini committed
1900
	  //update_difftimes(trx_time1, trx_time2);
1901 1902
      }

1903

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

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

1951 1952
      if (tx_pos >= openair0_cfg[card].samples_per_frame)
        tx_pos -= openair0_cfg[card].samples_per_frame;
1953 1954
    }

1955 1956
    if (rx_pos >= openair0_cfg[card].samples_per_frame)
      rx_pos -= openair0_cfg[card].samples_per_frame;
1957

Raymond Knopp's avatar
 
Raymond Knopp committed
1958 1959

#endif // USRP
1960

1961
    if (oai_exit) break;
Raymond Knopp's avatar
 
Raymond Knopp committed
1962

1963 1964 1965 1966 1967
    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;
1968

1969 1970
      if (time_diff < timing_info.time_min)
        timing_info.time_min = time_diff;
1971

1972 1973
      if (time_diff > timing_info.time_max)
        timing_info.time_max = time_diff;
1974

1975 1976 1977 1978 1979 1980
      timing_info.time_avg += time_diff;
    }

    timing_info.n_samples++;

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

2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033
	  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
2034
      }
2035 2036 2037 2038
    }

#ifdef EXMIMO
    slot++;
2039

2040 2041 2042 2043
    if (slot == 20) {
      frame++;
      slot = 0;
    }
2044

Raymond Knopp's avatar
 
Raymond Knopp committed
2045
#else
2046 2047
    hw_subframe++;
    slot += 2;
2048

2049
    if (hw_subframe == NUM_ENB_THREADS) {
2050
      // the radio frame is complete, start over
2051 2052 2053 2054
      hw_subframe = 0;
      frame++;
      slot = 1;
    }
2055 2056

#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2057

2058
#if defined(ENABLE_ITTI)
2059
    itti_update_lte_time( frame, slot );
2060
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2061
  }
2062 2063

eNB_thread_cleanup:
Raymond Knopp's avatar
 
Raymond Knopp committed
2064
#ifdef DEBUG_THREADS
2065
  printf( "eNB_thread: finished, ran %d times.\n", frame );
Raymond Knopp's avatar
 
Raymond Knopp committed
2066
#endif
2067

2068
#ifdef HARD_RT
Raymond Knopp's avatar
 
Raymond Knopp committed
2069
  rt_make_soft_real_time();
2070 2071
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
2072
#ifdef DEBUG_THREADS
2073
  printf( "Exiting eNB_thread ..." );
Raymond Knopp's avatar
 
Raymond Knopp committed
2074 2075
#endif
  // clean task
2076
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
2077
  rt_task_delete(task);
2078
#endif
2079 2080

  eNB_thread_status = 0;
2081

2082
  // print_difftimes();
2083

2084
  return &eNB_thread_status;
Raymond Knopp's avatar
 
Raymond Knopp committed
2085
}
2086

2087

Raymond Knopp's avatar
 
Raymond Knopp committed
2088

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2089

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



2108 2109

  const Enb_properties_array_t *enb_properties;
2110

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

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

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

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

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

2184 2185 2186 2187 2188
    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;
2189

2190 2191 2192
    case LONG_OPTION_DEBUG_UE_PRACH:
      mode = debug_prach;
      break;
2193

2194 2195 2196
    case LONG_OPTION_NO_L2_CONNECT:
      mode = no_L2_connect;
      break;
2197

Raymond Knopp's avatar
 
Raymond Knopp committed
2198 2199 2200 2201
    case LONG_OPTION_CALIB_PRACH_TX:
      mode = calib_prach_tx;
      break;

2202
    case LONG_OPTION_RXGAIN:
2203 2204
      for (i=0; i<4; i++)
        rx_gain[0][i] = atof(optarg);
2205

2206
      break;
2207

2208 2209 2210
    case LONG_OPTION_TXGAIN:
      for (i=0; i<4; i++)
        tx_gain[0][i] = atof(optarg);
2211

2212
      break;
2213

2214 2215 2216 2217 2218
    case LONG_OPTION_SCANCARRIER:
      UE_scan_carrier=1;

      break;

2219 2220 2221 2222 2223 2224
    case LONG_OPTION_LOOPMEMORY:
      mode=loop_through_memory;
      input_fd = fopen(optarg,"r");
      AssertFatal(input_fd != NULL,"Please provide an input file\n");
      break;

2225 2226 2227 2228
    case LONG_OPTION_DUMP_FRAME:
      mode = rx_dump_frame;
      break;
      
2229 2230 2231
    case LONG_OPTION_PHYTEST:
      phy_test = 1;
      break;
2232
      
2233 2234 2235 2236
    case 'A':
      timing_advance = atoi (optarg);
      break;

2237
    case 'C':
2238 2239 2240 2241 2242 2243
      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]);
2244
      }
2245

2246
      UE_scan=0;
2247

2248
      break;
2249

Florian Kaltenberger's avatar
Florian Kaltenberger committed
2250 2251 2252 2253
    case 'a':
      chain_offset = atoi(optarg);
      break;

2254 2255 2256 2257
    case 'd':
#ifdef XFORMS
      do_forms=1;
      printf("Running with XFORMS!\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2258
#endif
2259
      break;
2260 2261 2262 2263
      
    case 'E':
      threequarter_fs=1;
      break;
2264

2265 2266 2267
    case 'K':
#if defined(ENABLE_ITTI)
      itti_dump_file = strdup(optarg);
2268
#else
2269
      printf("-K option is disabled when ENABLE_ITTI is not defined\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2270
#endif
2271
      break;
2272

2273 2274 2275
    case 'O':
      conf_config_file_name = optarg;
      break;
2276

2277 2278 2279
    case 'U':
      UE_flag = 1;
      break;
2280

2281 2282 2283
    case 'm':
      target_dl_mcs = atoi (optarg);
      break;
2284

2285 2286 2287
    case 't':
      target_ul_mcs = atoi (optarg);
      break;
2288

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

2307
    case 'P':
2308 2309
      opt_type = OPT_PCAP;
      opt_enabled=1;
2310 2311 2312 2313 2314

      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");
2315
      } else {
2316 2317 2318
        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);
2319
      }
2320 2321 2322

      break;

Raymond Knopp's avatar
 
Raymond Knopp committed
2323 2324 2325
    case 'V':
      ouput_vcd = 1;
      break;
2326

Raymond Knopp's avatar
 
Raymond Knopp committed
2327
    case  'q':
Raymond Knopp's avatar
 
Raymond Knopp committed
2328 2329
      opp_enabled = 1;
      break;
2330

Raymond Knopp's avatar
 
Raymond Knopp committed
2331 2332 2333
    case  'R' :
      online_log_messages =1;
      break;
2334

Raymond Knopp's avatar
 
Raymond Knopp committed
2335
    case 'r':
2336
      UE_scan = 0;
2337

2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363
      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
2364
      }
2365

2366
      break;
2367

Raymond Knopp's avatar
 
Raymond Knopp committed
2368
    case 's':
2369
#if defined(OAI_USRP) || defined(CPRIGW)
Raymond Knopp's avatar
 
Raymond Knopp committed
2370 2371

      clock_src = atoi(optarg);
2372

Raymond Knopp's avatar
 
Raymond Knopp committed
2373
      if (clock_src == 0) {
2374 2375 2376 2377 2378
        //  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
2379
      }
2380

Raymond Knopp's avatar
 
Raymond Knopp committed
2381 2382 2383 2384
#else
      printf("Note: -s not defined for ExpressMIMO2\n");
#endif
      break;
2385

2386 2387 2388 2389
    case 'S':
      exit_missed_slots=0;
      printf("Skip exit for missed slots\n");
      break;
2390

2391
    case 'g':
Raymond Knopp's avatar
 
Raymond Knopp committed
2392
      glog_level=atoi(optarg); // value between 1 - 9
2393
      break;
2394 2395

    case 'F':
2396
#ifdef EXMIMO
2397 2398
      sprintf(rxg_fname,"%srxg.lime",optarg);
      rxg_fd = fopen(rxg_fname,"r");
2399

2400
      if (rxg_fd) {
2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418
        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);

2419
#endif
2420
      break;
2421

2422 2423 2424
    case 'G':
      glog_verbosity=atoi(optarg);// value from 0, 0x5, 0x15, 0x35, 0x75
      break;
2425

2426 2427
    case 'x':
      transmission_mode = atoi(optarg);
2428

2429 2430
      if (transmission_mode > 7) {
        printf("Transmission mode %d not supported for the moment\n",transmission_mode);
2431
        exit(-1);
2432
      }
2433
      break;
2434

2435 2436 2437
    case 'T':
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) 
	frame_parms[CC_id]->frame_type = TDD;
2438
      break;
2439

2440 2441 2442 2443
    case 'h':
      help ();
      exit (-1);
       
Raymond Knopp's avatar
 
Raymond Knopp committed
2444
    default:
2445 2446
      help ();
      exit (-1);
Raymond Knopp's avatar
 
Raymond Knopp committed
2447
      break;
2448 2449
    }
  }
2450

Raymond Knopp's avatar
 
Raymond Knopp committed
2451 2452
  if (UE_flag == 0)
    AssertFatal(conf_config_file_name != NULL,"Please provide a configuration file\n");
2453 2454


Raymond Knopp's avatar
 
Raymond Knopp committed
2455
  if ((UE_flag == 0) && (conf_config_file_name != NULL)) {
2456
    int i,j;
2457

Raymond Knopp's avatar
 
Raymond Knopp committed
2458
    NB_eNB_INST = 1;
2459

Raymond Knopp's avatar
 
Raymond Knopp committed
2460 2461
    /* Read eNB configuration file */
    enb_properties = enb_config_init(conf_config_file_name);
2462

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

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

2473 2474
      for (j=0; j<enb_properties->properties[i]->nb_rrh_gw; j++) {
	
2475 2476 2477 2478 2479 2480 2481 2482 2483 2484
	if (enb_properties->properties[i]->rrh_gw_config[j].active == 1 ) {
	  local_remote_radio = BBU_REMOTE_RADIO_HEAD;
	  eth_params = (eth_params_t*)malloc(sizeof(eth_params_t));
	  memset(eth_params, 0, sizeof(eth_params_t));
	  
	  eth_params->local_if_name             = enb_properties->properties[i]->rrh_gw_if_name;
	  eth_params->my_addr                   = enb_properties->properties[i]->rrh_gw_config[j].local_address;
	  eth_params->my_port                   = enb_properties->properties[i]->rrh_gw_config[j].local_port;
	  eth_params->remote_addr               = enb_properties->properties[i]->rrh_gw_config[j].remote_address;
	  eth_params->remote_port               = enb_properties->properties[i]->rrh_gw_config[j].remote_port;
2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501
	  eth_params->transp_preference         = enb_properties->properties[i]->rrh_gw_config[j].raw;	 
	  eth_params->iq_txshift                = enb_properties->properties[i]->rrh_gw_config[j].iq_txshift;
	  eth_params->tx_sample_advance         = enb_properties->properties[i]->rrh_gw_config[j].tx_sample_advance;
	  eth_params->tx_scheduling_advance     = enb_properties->properties[i]->rrh_gw_config[j].tx_scheduling_advance;
	  if (enb_properties->properties[i]->rrh_gw_config[j].exmimo == 1) {
	     eth_params->rf_preference          = EXMIMO_DEV;
	  } else if (enb_properties->properties[i]->rrh_gw_config[j].usrp_b200 == 1) {
	    eth_params->rf_preference          = USRP_B200_DEV;
	  } else if (enb_properties->properties[i]->rrh_gw_config[j].usrp_x300 == 1) {
	   eth_params->rf_preference          = USRP_X300_DEV;
	  } else if (enb_properties->properties[i]->rrh_gw_config[j].bladerf == 1) {
	    eth_params->rf_preference          = BLADERF_DEV;
	  } else if (enb_properties->properties[i]->rrh_gw_config[j].lmssdr == 1) {
	    //eth_params->rf_preference          = LMSSDR_DEV;
	  } else {
	    eth_params->rf_preference          = 0;
	  } 
2502 2503
	} else {
	  local_remote_radio = BBU_LOCAL_RADIO_HEAD; 
2504 2505 2506 2507
	}
	
      }

2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521
      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
2522 2523
      }

2524

2525 2526 2527
      init_all_otg(0);
      g_otg->seed = 0;
      init_seeds(g_otg->seed);
2528 2529 2530 2531 2532 2533 2534 2535 2536 2537

      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");
2538
      }
2539

2540
      init_predef_traffic(enb_properties->properties[i]->num_otg_elements, 1);
2541 2542


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

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

2593 2594
int main( int argc, char **argv )
{
2595
  int i,aa,card=0;
Lionel Gauthier's avatar
Lionel Gauthier committed
2596
#if defined (XFORMS) || defined (EMOS) || defined (EXMIMO)
Raymond Knopp's avatar
 
Raymond Knopp committed
2597
  void *status;
2598
#endif
2599

Raymond Knopp's avatar
 
Raymond Knopp committed
2600
  int CC_id;
Raymond Knopp's avatar
 
Raymond Knopp committed
2601
  uint16_t Nid_cell = 0;
2602
  uint8_t  cooperation_flag=0,  abstraction_flag=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2603
  uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2;
2604 2605

#ifdef ENABLE_TCXO
Raymond Knopp's avatar
 
Raymond Knopp committed
2606
  unsigned int tcxo = 114;
2607 2608
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
2609
#if defined (XFORMS)
2610 2611
  int ret;
#endif
2612
#if defined (EMOS) || (! defined (RTAI))
Raymond Knopp's avatar
 
Raymond Knopp committed
2613
  int error_code;
2614
#endif
2615

2616 2617 2618 2619 2620
#ifdef DEBUG_CONSOLE
  setvbuf(stdout, NULL, _IONBF, 0);
  setvbuf(stderr, NULL, _IONBF, 0);
#endif

2621 2622 2623
  PHY_VARS_UE *UE[MAX_NUM_CCs];

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

2626
  memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
Raymond Knopp's avatar
 
Raymond Knopp committed
2627
  set_latency_target();
2628

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

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

2665 2666
  //randominit (0);
  set_taus_seed (0);
Raymond Knopp's avatar
 
Raymond Knopp committed
2667

2668 2669
  if (UE_flag==1) {
    printf("configuring for UE\n");
2670

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

2687 2688 2689 2690 2691 2692 2693 2694
    set_comp_log(HW,      hw_log_level, hw_log_verbosity, 1);
    set_comp_log(PHY,     phy_log_level,   phy_log_verbosity, 1);
    if (opt_enabled == 1 )
      set_comp_log(OPT,   opt_log_level,      opt_log_verbosity, 1);
    set_comp_log(MAC,     mac_log_level,  mac_log_verbosity, 1);
    set_comp_log(RLC,     rlc_log_level,   rlc_log_verbosity, 1);
    set_comp_log(PDCP,    pdcp_log_level,  pdcp_log_verbosity, 1);
    set_comp_log(RRC,     rrc_log_level,  rrc_log_verbosity, 1);
2695
#if defined(ENABLE_ITTI)
2696
    set_comp_log(EMU,     LOG_INFO,   LOG_MED, 1);
2697
# if defined(ENABLE_USE_MME)
2698 2699 2700 2701
    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);
2702
# endif
2703
#if defined(ENABLE_SECURITY)
2704
    set_comp_log(OSA,    osa_log_level,   osa_log_verbosity, 1);
2705
#endif
2706
#endif
2707
#ifdef LOCALIZATION
2708 2709 2710 2711 2712 2713 2714 2715 2716
    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
2717
    }
2718
  }
2719

Raymond Knopp's avatar
 
Raymond Knopp committed
2720 2721
  if (ouput_vcd) {
    if (UE_flag==1)
2722
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_UE.vcd");
Raymond Knopp's avatar
 
Raymond Knopp committed
2723
    else
2724
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_eNB.vcd");
Raymond Knopp's avatar
 
Raymond Knopp committed
2725
  }
2726

2727
  if (opp_enabled ==1){
2728
    reset_opp_meas();
2729 2730
  }
  cpuf=get_cpu_freq_GHz();
2731

2732
#if defined(ENABLE_ITTI)
2733

Raymond Knopp's avatar
 
Raymond Knopp committed
2734 2735
  if (UE_flag == 1) {
    log_set_instance_type (LOG_INSTANCE_UE);
2736
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
2737 2738
    log_set_instance_type (LOG_INSTANCE_ENB);
  }
2739

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

2749 2750
    if (frame_parms[0]->frame_type == FDD)
      radio_type = RADIO_TYPE_FDD;
2751
    else
2752
      radio_type = RADIO_TYPE_TDD;
2753

2754 2755 2756
    if (init_opt(in_path, in_ip, NULL, radio_type) == -1)
      LOG_E(OPT,"failed to run OPT \n");
  }
2757

2758
#ifdef PDCP_USE_NETLINK
Raymond Knopp's avatar
 
Raymond Knopp committed
2759
  netlink_init();
2760 2761 2762
#if defined(PDCP_USE_NETLINK_QUEUES)
  pdcp_netlink_init();
#endif
2763 2764
#endif

2765
#if !defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
2766 2767 2768
  // to make a graceful exit when ctrl-c is pressed
  signal(SIGSEGV, signal_handler);
  signal(SIGINT, signal_handler);
2769
#endif
2770 2771

#ifndef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
2772 2773 2774 2775
  check_clock();
#endif

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

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


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

  if (UE_flag==1) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2816 2817 2818
    NB_UE_INST=1;
    NB_INST=1;

Raymond Knopp's avatar
 
Raymond Knopp committed
2819 2820
    PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE**));
    PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_UE*)*MAX_NUM_CCs);
2821 2822

    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
2823 2824 2825 2826

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

2828 2829 2830 2831
      if (phy_test==1)
	UE[CC_id]->mac_enabled = 0;
      else 
	UE[CC_id]->mac_enabled = 1;
2832

2833 2834 2835 2836 2837 2838 2839 2840 2841 2842
      if (UE[CC_id]->mac_enabled == 0) {
	for (i=0; i<NUMBER_OF_CONNECTED_eNB_MAX; i++) {
	  UE[CC_id]->pusch_config_dedicated[i].betaOffset_ACK_Index = beta_ACK;
	  UE[CC_id]->pusch_config_dedicated[i].betaOffset_RI_Index  = beta_RI;
	  UE[CC_id]->pusch_config_dedicated[i].betaOffset_CQI_Index = beta_CQI;
	  
	  UE[CC_id]->scheduling_request_config[i].sr_PUCCH_ResourceIndex = 0;
	  UE[CC_id]->scheduling_request_config[i].sr_ConfigIndex = 7+(0%3);
	  UE[CC_id]->scheduling_request_config[i].dsr_TransMax = sr_n4;
	}
Raymond Knopp's avatar
 
Raymond Knopp committed
2843
      }
2844

2845
      UE[CC_id]->UE_scan = UE_scan;
2846
      UE[CC_id]->UE_scan_carrier = UE_scan_carrier;
2847 2848 2849
      UE[CC_id]->mode    = mode;

      compute_prach_seq(&UE[CC_id]->lte_frame_parms.prach_config_common,
2850 2851 2852
                        UE[CC_id]->lte_frame_parms.frame_type,
                        UE[CC_id]->X_u);

2853 2854 2855 2856
      if (UE[CC_id]->mac_enabled == 1) 
	UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1234;
      else
	UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1235;
2857

2858
#ifdef EXMIMO
2859 2860 2861 2862
      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
2863
      }
2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882

      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
2883
      }
2884

2885
#else
2886
      UE[CC_id]->rx_total_gain_dB =  (int)rx_gain[CC_id][0];
2887
#endif
2888

2889
      UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id];
2890

2891

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

Raymond Knopp's avatar
 
Raymond Knopp committed
2910 2911 2912 2913
    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;
2914 2915 2916



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

2927 2928 2929 2930
      if (phy_test==1)
	PHY_vars_eNB_g[0][CC_id]->mac_enabled = 0;
      else 
	PHY_vars_eNB_g[0][CC_id]->mac_enabled = 1;
2931

2932 2933 2934 2935 2936 2937 2938 2939 2940 2941
      if (PHY_vars_eNB_g[0][CC_id]->mac_enabled == 0) {
	for (i=0; i<NUMBER_OF_UE_MAX; i++) {
	  PHY_vars_eNB_g[0][CC_id]->pusch_config_dedicated[i].betaOffset_ACK_Index = beta_ACK;
	  PHY_vars_eNB_g[0][CC_id]->pusch_config_dedicated[i].betaOffset_RI_Index  = beta_RI;
	  PHY_vars_eNB_g[0][CC_id]->pusch_config_dedicated[i].betaOffset_CQI_Index = beta_CQI;
	  
	  PHY_vars_eNB_g[0][CC_id]->scheduling_request_config[i].sr_PUCCH_ResourceIndex = i;
	  PHY_vars_eNB_g[0][CC_id]->scheduling_request_config[i].sr_ConfigIndex = 7+(i%3);
	  PHY_vars_eNB_g[0][CC_id]->scheduling_request_config[i].dsr_TransMax = sr_n4;
	}
2942 2943 2944 2945 2946
      }

      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
2947

2948
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
2949

2950
      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
2951

2952
#else
2953 2954 2955
      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
2956

2957 2958 2959
      // 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
2960

2961
#endif
2962

2963
#ifdef EXMIMO
2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974

      //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
2975
      }
2976

2977
#else
2978
      //already taken care of in lte-softmodem.c
2979 2980
      PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 0;
#endif
2981

2982
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
2983 2984


2985 2986 2987 2988 2989 2990 2991 2992 2993
    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;

  }
2994 2995 2996 2997
#ifndef RTAI
  fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx);
  cpuf=get_cpu_freq_GHz();
#endif 
2998

Raymond Knopp's avatar
 
Raymond Knopp committed
2999
  dump_frame_parms(frame_parms[0]);
3000

3001 3002 3003
  for (card=0; card<MAX_CARDS; card++) {

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

    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
3038

3039 3040 3041 3042 3043 3044
    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;    
    }
3045

3046
    printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card,
3047 3048
           ((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
3049 3050
    openair0_cfg[card].Mod_id = 0;
#ifdef ETHERNET
3051 3052

    if (UE_flag) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3053
      printf("ETHERNET: Configuring UE ETH for %s:%d\n",rrh_UE_ip,rrh_UE_port);
3054
      openair0_cfg[card].remote_addr   = &rrh_UE_ip[0];
3055
      openair0_cfg[card].remote_port = rrh_UE_port;
3056 3057
    } 

3058
    openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL;
Raymond Knopp's avatar
 
Raymond Knopp committed
3059
#endif
3060

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

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

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

3087
#if 0  // UHD 3.8     
3088 3089
      switch(frame_parms[0]->N_RB_DL) {
      case 6:
3090
        openair0_cfg[card].rx_gain[i] -= 12;
3091 3092
        break;

3093
      case 25:
3094
        openair0_cfg[card].rx_gain[i] -= 6;
3095 3096
        break;

3097
      case 50:
3098 3099 3100 3101 3102
        openair0_cfg[card].rx_gain[i] -= 3;
        break;

      case 100:
        openair0_cfg[card].rx_gain[i] -= 0;
3103 3104
        break;

3105
      default:
3106
        break;
3107
      }
3108
#endif      
3109

Raymond Knopp's avatar
 
Raymond Knopp committed
3110
    }
3111

3112
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3113
  }
3114 3115 3116 3117 3118 3119
  /* 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
3120
  openair0_cfg[0].log_level = glog_level;
3121

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

  mac_xface = malloc(sizeof(MAC_xface));

Raymond Knopp's avatar
 
Raymond Knopp committed
3152
  int eMBMS_active=0;
3153
  
Raymond Knopp's avatar
 
Raymond Knopp committed
3154
  l2_init(frame_parms[0],eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL,
3155 3156 3157
	  0,// cba_group_active
	  0); // HO flag
  
Raymond Knopp's avatar
 
Raymond Knopp committed
3158
  mac_xface->macphy_exit = &exit_fun;
3159

winckel's avatar
winckel committed
3160
#if defined(ENABLE_ITTI)
3161

Raymond Knopp's avatar
 
Raymond Knopp committed
3162
  if (create_tasks(UE_flag ? 0 : 1, UE_flag ? 1 : 0) < 0) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3163
    printf("cannot create ITTI tasks\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3164 3165
    exit(-1); // need a softer mode
  }
3166

Raymond Knopp's avatar
 
Raymond Knopp committed
3167
  printf("ITTI tasks created\n");
winckel's avatar
winckel committed
3168
#endif
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3169

3170 3171 3172 3173 3174 3175 3176 3177
  if (phy_test==0) {
    if (UE_flag==1) {
      printf("Filling UE band info\n");
      fill_ue_band_info();
      mac_xface->dl_phy_sync_success (0, 0, 0, 1);
    } else
      mac_xface->mrbch_phy_sync_failure (0, 0, 0);
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
3178

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

3197
#ifdef EXMIMO
3198
  number_of_cards = openair0_num_detected_cards;
3199 3200
#else
  number_of_cards = 1;
3201
#endif
3202

3203

3204

3205
  for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3206
    rf_map[CC_id].card=0;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3207
    rf_map[CC_id].chain=CC_id+chain_offset;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3208
  }
3209

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

3222
    printf("Setting UE buffer to all-RX\n");
3223

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

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

3243 3244 3245 3246
    if (setup_eNB_buffers(PHY_vars_eNB_g[0],&openair0_cfg[0],rf_map)!=0) {
      printf("Error setting up eNB buffer\n");
      exit(-1);
    }
3247

3248
    printf("Setting eNB buffer to all-RX\n");
3249

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

3258
#ifdef EXMIMO
3259
  openair0_config(&openair0_cfg[0],UE_flag);
Raymond Knopp's avatar
 
Raymond Knopp committed
3260 3261
#endif

3262
  /*
Raymond Knopp's avatar
 
Raymond Knopp committed
3263 3264
      for (ant=0;ant<4;ant++)
      p_exmimo_config->rf.do_autocal[ant] = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3265
  */
3266 3267

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

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

3279 3280
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3281
  mlockall(MCL_CURRENT | MCL_FUTURE);
3282 3283

#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3284
  // make main thread LXRT soft realtime
3285
  /* task = */ rt_task_init_schmod(nam2num("MAIN"), 9, 0, 0, SCHED_FIFO, 0xF);
Raymond Knopp's avatar
 
Raymond Knopp committed
3286 3287 3288 3289 3290

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3293 3294
  pthread_cond_init(&sync_cond,NULL);
  pthread_mutex_init(&sync_mutex, NULL);
3295

3296
  /*  this is moved to the eNB main thread */ 
3297

3298
//#if defined(ENABLE_ITTI)
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3299
  // Wait for eNB application initialization to be complete (eNB registration to MME)
3300 3301 3302 3303 3304
  //  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
3305

Raymond Knopp's avatar
 
Raymond Knopp committed
3306 3307

  // this starts the DMA transfers
3308
#ifdef EXMIMO
3309

Raymond Knopp's avatar
 
Raymond Knopp committed
3310
  if (UE_flag!=1)
3311
    for (card=0; card<openair0_num_detected_cards; card++)
3312
      openair0_start_rt_acquisition(card);
3313

Raymond Knopp's avatar
 
Raymond Knopp committed
3314
#endif
3315 3316

#ifdef XFORMS
3317 3318
  int UE_id;

Raymond Knopp's avatar
 
Raymond Knopp committed
3319 3320
  if (do_forms==1) {
    fl_initialize (&argc, argv, NULL, 0, 0);
3321 3322

    if (UE_flag==0) {
3323
      form_stats_l2 = create_form_stats_form();
3324 3325 3326
      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");
3327 3328

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

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

3362 3363
    if (ret == 0)
      pthread_setname_np( forms_thread, "xforms" );
3364

Raymond Knopp's avatar
 
Raymond Knopp committed
3365 3366
    printf("Scope thread created, ret=%d\n",ret);
  }
3367

3368 3369 3370
#endif

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3371 3372
  ret = pthread_create(&thread3, NULL, emos_thread, NULL);
  printf("EMOS thread created, ret=%d\n",ret);
jiangx's avatar
jiangx committed
3373 3374
  ret = pthread_create(&thread4, NULL, gps_thread, NULL);
  printf("GPS thread created, ret=%d\n",ret);
3375 3376
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3377
  rt_sleep_ns(10*FRAME_PERIOD);
3378 3379

#ifndef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3380
  pthread_attr_init (&attr_dlsch_threads);
3381
  pthread_attr_setstacksize(&attr_dlsch_threads,4*PTHREAD_STACK_MIN);
3382

3383
  pthread_attr_init (&attr_UE_thread);
3384
  pthread_attr_setstacksize(&attr_UE_thread,8192);//5*PTHREAD_STACK_MIN);
3385

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

3395 3396
#endif

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

3407
    sleep(1);
3408
#ifdef RTAI
3409
    main_ue_thread = rt_thread_create(UE_thread, NULL, 100000000);
3410
#else
3411
    error_code = pthread_create(&main_ue_thread, &attr_UE_thread, UE_thread, NULL);
3412

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

3421
#endif
3422
    printf("UE threads created\n");
3423 3424 3425 3426 3427 3428 3429 3430 3431 3432
#ifdef USE_MME

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

#endif



3433
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
3434 3435
    if (multi_thread>0) {
      init_eNB_proc();
3436
      sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3437 3438
      LOG_D(HW,"[lte-softmodem.c] eNB threads created\n");
    }
3439

3440
    printf("Creating main eNB_thread \n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3441
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3442
    main_eNB_thread = rt_thread_create(eNB_thread, NULL, PTHREAD_STACK_MIN);
Raymond Knopp's avatar
 
Raymond Knopp committed
3443
#else
3444
    error_code = pthread_create( &main_eNB_thread, &attr_dlsch_threads, eNB_thread, NULL );
3445

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3454 3455
#endif
  }
3456

Raymond Knopp's avatar
 
Raymond Knopp committed
3457
  // Sleep to allow all threads to setup
Raymond Knopp's avatar
 
Raymond Knopp committed
3458
  sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3459

3460

3461

3462
#ifndef EXMIMO
3463

Raymond Knopp's avatar
 
Raymond Knopp committed
3464
#ifndef USRP_DEBUG
3465
  if (mode!=loop_through_memory)
navid's avatar
navid committed
3466 3467 3468
    if (openair0.trx_start_func(&openair0) != 0 ) 
      LOG_E(HW,"Could not start the device\n");

Raymond Knopp's avatar
 
Raymond Knopp committed
3469
#endif
3470

3471 3472
#endif

3473
  printf("Sending sync to all threads\n");
3474

Raymond Knopp's avatar
 
Raymond Knopp committed
3475
  pthread_mutex_lock(&sync_mutex);
3476
  sync_var=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3477 3478
  pthread_cond_broadcast(&sync_cond);
  pthread_mutex_unlock(&sync_mutex);
3479

Raymond Knopp's avatar
 
Raymond Knopp committed
3480 3481 3482
  // wait for end of program
  printf("TYPE <CTRL-C> TO TERMINATE\n");
  //getchar();
3483 3484

#if defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
3485 3486
  printf("Entering ITTI signals handler\n");
  itti_wait_tasks_end();
3487
  oai_exit=1;
3488
#else
3489

Raymond Knopp's avatar
 
Raymond Knopp committed
3490 3491
  while (oai_exit==0)
    rt_sleep_ns(FRAME_PERIOD);
3492

3493
#endif
3494

Raymond Knopp's avatar
 
Raymond Knopp committed
3495
  // stop threads
3496
#ifdef XFORMS
Raymond Knopp's avatar
 
Raymond Knopp committed
3497
  printf("waiting for XFORMS thread\n");
3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511

  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++) {
3512 3513 3514 3515
	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
3516
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
3517
    }
3518 3519
  }

3520 3521
#endif

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

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

3548
    if (result != 0) {
3549
      printf( "\nError joining main_eNB_thread.\n" );
3550
    } else {
3551 3552 3553 3554 3555
      if (eNB_thread_status_p) {
        printf( "status %d\n", *eNB_thread_status_p );
      } else {
        printf( "The thread was killed. No status available.\n");
      }
3556
    }
3557

3558 3559
#else
    UNUSED(result);
3560 3561
#endif // DEBUG_THREADS
#endif // RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3562

Raymond Knopp's avatar
 
Raymond Knopp committed
3563 3564 3565
    if (multi_thread>0) {
      printf("Killing eNB processing threads\n");
      kill_eNB_proc();
Raymond Knopp's avatar
 
Raymond Knopp committed
3566
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3567
  }
3568

3569

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

3576

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3600
  if (ouput_vcd)
3601
    VCD_SIGNAL_DUMPER_CLOSE();
3602

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3606
  logClean();
3607

Raymond Knopp's avatar
 
Raymond Knopp committed
3608 3609
  return 0;
}
3610 3611


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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3627

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

3637
#ifndef EXMIMO
3638

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3648
#endif
3649

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

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

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

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

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

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

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

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

      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;
3696
      }
3697
    }
3698

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3719
    }
3720

Raymond Knopp's avatar
 
Raymond Knopp committed
3721
#endif
3722
  }
3723

3724
  return(0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3725
}
3726

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

3738 3739
void print_opp_meas(void) {

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