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 = 2;
168 169 170
#endif //XFORMS

#ifdef RTAI
171

172 173
static long                      main_eNB_thread;
static long                      main_ue_thread;
174

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

179
pthread_attr_t                  attr_dlsch_threads;
180 181
pthread_attr_t                  attr_UE_thread;

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

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

191

192 193


194
struct sched_param              sched_param_UE_thread;
195

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
212

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

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

223

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
234

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

238
static char                     threequarter_fs=0;
239

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

243
openair0_rf_map rf_map[MAX_NUM_CCs];
244

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

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

254 255
FILE *input_fd=NULL;

256

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

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

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

293 294
char   rf_config_file[1024];

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

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

#endif
302 303

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
326

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
363 364 365

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  oai_exit = 1;

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

  //rt_sleep_ns(FRAME_PERIOD);

  //exit (-1);
}

509

510
#ifdef XFORMS
511

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

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

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

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

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

543 544
static void *scope_thread(void *arg)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
545
  char stats_buffer[16384];
546
# ifdef ENABLE_XFORMS_WRITE_STATS
Raymond Knopp's avatar
 
Raymond Knopp committed
547
  FILE *UE_stats, *eNB_stats;
548
# endif
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
549
  int len = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
550
  struct sched_param sched_param;
551
  int UE_id, CC_id;
552
  int ue_cnt=0;
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 {
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
581 582
#ifdef OPENAIR2
      len = dump_eNB_l2_stats (stats_buffer, 0);
knopp's avatar
knopp committed
583 584 585
      //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
586 587
#endif
      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 597
      ue_cnt=0;
      for(UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
598
	for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
599
	  if ((PHY_vars_eNB_g[0][CC_id]->dlsch_eNB[UE_id][0]->rnti>0) && (ue_cnt<scope_enb_num_ue)) {
gauthier's avatar
gauthier committed
600
	    phy_scope_eNB(form_enb[CC_id][ue_cnt],
601 602 603 604
			  PHY_vars_eNB_g[0][CC_id],
			  UE_id);
	    ue_cnt++;
	  }
605
	}
Raymond Knopp's avatar
 
Raymond Knopp committed
606
      }
607

608
    }
609

Raymond Knopp's avatar
 
Raymond Knopp committed
610
    //printf("doing forms\n");
Florian Kaltenberger's avatar
Florian Kaltenberger committed
611 612
    //usleep(100000); // 100 ms
    sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
613
  }
614

615
  //  printf("%s",stats_buffer);
616

617
# ifdef ENABLE_XFORMS_WRITE_STATS
618

619 620 621 622 623 624
  if (UE_flag==1) {
    if (UE_stats) {
      rewind (UE_stats);
      fwrite (stats_buffer, 1, len, UE_stats);
      fclose (UE_stats);
    }
625
  } else {
626 627 628 629 630 631
    if (eNB_stats) {
      rewind (eNB_stats);
      fwrite (stats_buffer, 1, len, eNB_stats);
      fclose (eNB_stats);
    }
  }
632

633
# endif
634

Raymond Knopp's avatar
 
Raymond Knopp committed
635
  pthread_exit((void*)arg);
636 637 638 639 640 641
}
#endif

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

jiangx's avatar
jiangx committed
642 643 644 645 646 647 648 649
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;

650
  sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
jiangx's avatar
jiangx committed
651
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
652

jiangx's avatar
jiangx committed
653 654 655
  printf("GPS thread has priority %d\n",sched_param.sched_priority);

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

jiangx's avatar
jiangx committed
657 658
#if GPSD_API_MAJOR_VERSION>=5
  ret = gps_open("127.0.0.1","2947",gps_data_ptr);
659

jiangx's avatar
jiangx committed
660 661 662
  if (ret!=0)
#else
  gps_data_ptr = gps_open("127.0.0.1","2947");
663 664

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

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

682 683 684

  while (!oai_exit) {
    printf("[EMOS] polling data from gps\n");
jiangx's avatar
jiangx committed
685
#if GPSD_API_MAJOR_VERSION>=5
686 687 688

    if (gps_waiting(gps_data_ptr,500)) {
      if (gps_read(gps_data_ptr) <= 0) {
jiangx's avatar
jiangx committed
689
#else
690 691 692 693 694 695 696 697

    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
698
      }
699 700 701 702 703 704 705 706
    } //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
707 708 709 710 711

  pthread_exit((void*) arg);

}

712 713 714 715 716 717 718 719 720 721 722
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;
723

jiangx's avatar
jiangx committed
724
  int channel_buffer_size,ret;
725

726 727 728
  time_t timer;
  struct tm *now;

729
  struct sched_param sched_param;
730 731

  sched_param.sched_priority = sched_get_priority_max(SCHED_FIFO)-1;
732
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
733

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

736 737 738 739 740 741 742 743 744 745 746 747
  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;

748 749 750 751
  if (fifo2file_buffer == NULL) {
    printf("[EMOS] Cound not allocate memory for fifo2file_buffer\n");
    exit(EXIT_FAILURE);
  }
752

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


  time(&starttime_tmp);
  localtime_r(&starttime_tmp,&starttime);
  snprintf(dumpfile_name,1024,"/tmp/%s_data_%d%02d%02d_%02d%02d%02d.EMOS",
762 763
           (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);
764 765

  dumpfile_id = fopen(dumpfile_name,"w");
766 767 768 769 770

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


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

775 776 777 778 779 780 781
  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);
782

783 784 785 786
    if (bytes<=0) {
      usleep(100);
      continue;
    }
787

788 789 790
    if (bytes != channel_buffer_size) {
      printf("[EMOS] ERROR! Only got %d bytes instead of %d!\n",bytes,channel_buffer_size);
    }
791

792 793 794 795 796 797
    /*
    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);
    */
798

799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819
    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
820

821 822 823 824
      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);
      }
825
    }
826 827
  }

828 829 830
  free(fifo2file_buffer);
  fclose(dumpfile_id);
  close(fifo);
831

832 833 834 835 836
  pthread_exit((void*) arg);

}
#endif

837 838


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

    while ((!oai_exit) && (*start_flag == 0)) {
      LOG_N(EMU, message, indicator[i]);
851
      fflush(stdout);
852 853 854
      i = (i + 1) % (sizeof(indicator) / sizeof(indicator[0]));
      usleep(200000);
    }
855

856 857 858 859 860
    LOG_D(EMU,"\n");
  }
}
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
861
#if defined(ENABLE_ITTI)
862
void *l2l1_task(void *arg)
863
{
Raymond Knopp's avatar
 
Raymond Knopp committed
864 865 866 867 868
  MessageDef *message_p = NULL;
  int         result;

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
869

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

879 880 881
      itti_receive_msg (TASK_L2L1, &message_p);

      switch (ITTI_MSG_ID(message_p)) {
Raymond Knopp's avatar
 
Raymond Knopp committed
882
      case INITIALIZE_MESSAGE:
883 884 885 886
        /* 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
887 888

      case TERMINATE_MESSAGE:
889 890 891 892
        printf("received terminate message\n");
        oai_exit=1;
        itti_exit_task ();
        break;
Raymond Knopp's avatar
 
Raymond Knopp committed
893 894

      default:
895 896
        LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
        break;
897
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
898
    } while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE);
899

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

Raymond Knopp's avatar
 
Raymond Knopp committed
922 923 924 925 926 927 928 929 930 931 932
    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);
933
  } while(!oai_exit);
934

Raymond Knopp's avatar
 
Raymond Knopp committed
935
  return NULL;
936 937 938
}
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
939

940 941
void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
942 943 944 945

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

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
958

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

986 987 988 989 990
      // 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
991
      /*
992 993 994 995 996
      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
997
	}*/
998
      for (i=0; i<len; i++) {
999 1000
        tx_offset = (int)slot_offset+time_offset[aa]+i;

1001
	
1002 1003 1004 1005 1006 1007
        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;

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

     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
1037 1038 1039 1040
    }
  }
}

1041 1042 1043 1044 1045 1046 1047 1048 1049
/* 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
1050

1051 1052 1053 1054 1055 1056 1057 1058 1059
/*!
 * \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
1060 1061

  eNB_proc_t *proc = (eNB_proc_t*)param;
1062 1063
  FILE  *tx_time_file;
  char tx_time_name[101];
kaltenbe's avatar
kaltenbe committed
1064

1065 1066 1067 1068
  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");
  }
1069 1070 1071
  // set default return value
  eNB_thread_tx_status[proc->subframe] = 0;

1072 1073
  MSC_START_USE();

Raymond Knopp's avatar
 
Raymond Knopp committed
1074 1075
#ifdef RTAI
  RT_TASK *task;
1076
  char task_name[8];
Raymond Knopp's avatar
 
Raymond Knopp committed
1077

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

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

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

1103 1104 1105 1106
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1107

navid's avatar
navid committed
1108 1109 1110 1111
  attr.sched_policy   = SCHED_DEADLINE;
  attr.sched_runtime  = runtime;
  attr.sched_deadline = deadline;
  attr.sched_period   = period; 
1112

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1123 1124 1125 1126 1127 1128 1129 1130
#endif

  mlockall(MCL_CURRENT | MCL_FUTURE);

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

1131
  while (!oai_exit) {
1132

1133
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe), 0 );
1134

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

1141
    while (proc->instance_cnt_tx < 0) {
1142 1143 1144
      // 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
1145
    }
1146

1147 1148 1149 1150 1151
    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
1152

1153 1154
    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 );
1155 1156 1157
    start_meas( &softmodem_stats_tx_sf[proc->subframe] );

    if (oai_exit) break;
1158

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

1177 1178 1179
      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");
1180 1181
      }

1182 1183 1184
      if (oai_exit)
        break;

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

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

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

1224 1225 1226 1227 1228 1229 1230 1231 1232
    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++;
1233

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

1246 1247
  }

1248 1249


1250
  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
1251

Raymond Knopp's avatar
 
Raymond Knopp committed
1252 1253 1254
#ifdef HARD_RT
  rt_make_soft_real_time();
#endif
1255

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

1264 1265
  eNB_thread_tx_status[proc->subframe] = 0;
  return &eNB_thread_tx_status[proc->subframe];
Raymond Knopp's avatar
 
Raymond Knopp committed
1266 1267 1268
}


1269 1270 1271 1272 1273 1274 1275 1276 1277 1278
/*!
 * \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
1279
  eNB_proc_t *proc = (eNB_proc_t*)param;
1280

1281 1282
  FILE  *rx_time_file;
  char rx_time_name[101];
Raymond Knopp's avatar
 
Raymond Knopp committed
1283 1284
  int i;

1285 1286 1287 1288
  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");
  }
1289 1290 1291
  // set default return value
  eNB_thread_rx_status[proc->subframe] = 0;

1292 1293
  MSC_START_USE();

Raymond Knopp's avatar
 
Raymond Knopp committed
1294 1295
#ifdef RTAI
  RT_TASK *task;
1296
  char task_name[8];
Raymond Knopp's avatar
 
Raymond Knopp committed
1297

1298
  sprintf(task_name,"RXC%1dS%1d",proc->CC_id,proc->subframe);
Raymond Knopp's avatar
 
Raymond Knopp committed
1299 1300 1301
  task = rt_task_init_schmod(nam2num(task_name), 0, 0, 0, SCHED_FIFO, 0xF);

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

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

1324 1325 1326 1327
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1328

1329
  attr.sched_policy = SCHED_DEADLINE;
navid's avatar
navid committed
1330 1331 1332
  attr.sched_runtime  = runtime;
  attr.sched_deadline = deadline;
  attr.sched_period   = period; 
1333 1334

  if (sched_setattr(0, &attr, flags) < 0 ) {
1335
    perror("[SCHED] eNB RX sched_setattr failed\n");
1336
    return &eNB_thread_rx_status[proc->subframe];
1337
  }
1338

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

  mlockall(MCL_CURRENT | MCL_FUTURE);

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

1351
  while (!oai_exit) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1352

1353
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 0 );
1354

Raymond Knopp's avatar
 
Raymond Knopp committed
1355
    if (pthread_mutex_lock(&proc->mutex_rx) != 0) {
1356 1357 1358
      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
1359 1360
    }

1361
    while (proc->instance_cnt_rx < 0) {
1362 1363 1364
      // 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
1365
    }
1366 1367 1368 1369 1370 1371 1372

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

1373 1374
    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 );
1375
    start_meas( &softmodem_stats_rx_sf[proc->subframe] );
1376

Raymond Knopp's avatar
 
Raymond Knopp committed
1377
    if (oai_exit) break;
1378

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

1382
      phy_procedures_eNB_RX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay );
Raymond Knopp's avatar
 
Raymond Knopp committed
1383
    }
1384 1385

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

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

    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
1401
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1402 1403

    proc->frame_rx++;
1404

Raymond Knopp's avatar
 
Raymond Knopp committed
1405 1406
    if (proc->frame_rx==1024)
      proc->frame_rx=0;
1407

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

1419
  //stop_meas( &softmodem_stats_rx_sf[proc->subframe] );
1420
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 0 );
1421

Raymond Knopp's avatar
 
Raymond Knopp committed
1422
#ifdef HARD_RT
Raymond Knopp's avatar
 
Raymond Knopp committed
1423 1424 1425 1426
  rt_make_soft_real_time();
#endif

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

1434 1435
  eNB_thread_rx_status[proc->subframe] = 0;
  return &eNB_thread_rx_status[proc->subframe];
Raymond Knopp's avatar
 
Raymond Knopp committed
1436 1437 1438 1439
}



Raymond Knopp's avatar
 
Raymond Knopp committed
1440

1441 1442
void init_eNB_proc(void)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1443
  int i;
Raymond Knopp's avatar
 
Raymond Knopp committed
1444 1445
  int CC_id;

1446 1447 1448
  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
1449
     
1450

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


1502
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
1503 1504
    // 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
1505

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

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

1527 1528 1529 1530 1531 1532
/*!
 * \brief Terminate eNB TX and RX threads.
 */
void kill_eNB_proc(void)
{
  int *status;
Raymond Knopp's avatar
 
Raymond Knopp committed
1533

1534 1535
  for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++)
    for (int i=0; i<NUM_ENB_THREADS; i++) {
1536

Raymond Knopp's avatar
 
Raymond Knopp committed
1537
#ifdef DEBUG_THREADS
1538
      printf( "Killing TX CC_id %d thread %d\n", CC_id, i );
Raymond Knopp's avatar
 
Raymond Knopp committed
1539
#endif
1540 1541 1542

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1550
#ifdef DEBUG_THREADS
1551

1552 1553 1554 1555 1556 1557 1558 1559 1560
      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" );
        }
      }
1561

1562 1563
#else
      UNUSED(result)
Raymond Knopp's avatar
 
Raymond Knopp committed
1564
#endif
1565

Raymond Knopp's avatar
 
Raymond Knopp committed
1566
#ifdef DEBUG_THREADS
1567
      printf( "Killing RX CC_id %d thread %d\n", CC_id, i );
Raymond Knopp's avatar
 
Raymond Knopp committed
1568
#endif
1569 1570 1571 1572

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

1578 1579
#ifdef DEBUG_THREADS

1580 1581 1582 1583 1584 1585 1586 1587 1588
      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" );
        }
      }
1589

1590 1591
#else
      UNUSED(result)
Raymond Knopp's avatar
 
Raymond Knopp committed
1592
#endif
1593 1594 1595 1596 1597

      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
1598
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1599 1600 1601
}


Raymond Knopp's avatar
 
Raymond Knopp committed
1602 1603


1604

Raymond Knopp's avatar
 
Raymond Knopp committed
1605

1606 1607 1608 1609 1610 1611
/*!
 * \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 )
1612
{
1613 1614
  UNUSED(arg);
  static int eNB_thread_status;
1615

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

  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
1636

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

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

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

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

Lionel Gauthier's avatar
Lionel Gauthier committed
1663

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

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

1677
#endif
1678 1679
#endif

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

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

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

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

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

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

1710
  pthread_mutex_unlock(&sync_mutex);
1711

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

1714
  int frame = 0;
1715

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

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

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

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

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

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

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

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

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

    
1791
    }
1792

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

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

    delay_cnt = 0;
1801

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

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

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

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

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

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

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

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

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

1849
      clock_gettime( CLOCK_MONOTONIC, &trx_time0 );
1850

1851
       start_meas( &softmodem_stats_hw );
1852

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

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

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

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

1902

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

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1957 1958

#endif // USRP
1959

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

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

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

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

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

    timing_info.n_samples++;

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

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

#ifdef EXMIMO
    slot++;
2038

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

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

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

#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2056

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

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

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

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

  eNB_thread_status = 0;
2080

2081
  // print_difftimes();
2082

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

2086

Raymond Knopp's avatar
 
Raymond Knopp committed
2087

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2088

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



2107 2108

  const Enb_properties_array_t *enb_properties;
2109

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

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

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

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

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

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

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

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

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

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

2200
      break;
2201

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

2206
      break;
2207

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

      break;

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

   case LONG_OPTION_DUMP_FRAME:
     mode = rx_dump_frame;
2221
     break;   
2222 2223 2224 2225
    case 'A':
      timing_advance = atoi (optarg);
      break;

2226
    case 'C':
2227 2228 2229 2230 2231 2232
      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]);
2233
      }
2234

2235
      UE_scan=0;
2236

2237
      break;
2238

Florian Kaltenberger's avatar
Florian Kaltenberger committed
2239 2240 2241 2242
    case 'a':
      chain_offset = atoi(optarg);
      break;

2243 2244 2245 2246
    case 'd':
#ifdef XFORMS
      do_forms=1;
      printf("Running with XFORMS!\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2247
#endif
2248
      break;
2249 2250 2251 2252
      
    case 'E':
      threequarter_fs=1;
      break;
2253

2254 2255 2256
    case 'K':
#if defined(ENABLE_ITTI)
      itti_dump_file = strdup(optarg);
2257
#else
2258
      printf("-K option is disabled when ENABLE_ITTI is not defined\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2259
#endif
2260
      break;
2261

2262 2263 2264
    case 'O':
      conf_config_file_name = optarg;
      break;
2265

2266 2267 2268
    case 'U':
      UE_flag = 1;
      break;
2269

2270 2271 2272
    case 'm':
      target_dl_mcs = atoi (optarg);
      break;
2273

2274 2275 2276
    case 't':
      target_ul_mcs = atoi (optarg);
      break;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2277
#ifdef OPENAIR2
2278

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

2297
    case 'P':
2298 2299
      opt_type = OPT_PCAP;
      opt_enabled=1;
2300 2301 2302 2303 2304

      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");
2305
      } else {
2306 2307 2308
        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);
2309
      }
2310 2311

      break;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2312
#endif
2313

Raymond Knopp's avatar
 
Raymond Knopp committed
2314 2315 2316
    case 'V':
      ouput_vcd = 1;
      break;
2317

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
2326
    case 'r':
2327
      UE_scan = 0;
2328

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

2357
      break;
2358

Raymond Knopp's avatar
 
Raymond Knopp committed
2359
    case 's':
2360
#if defined(OAI_USRP) || defined(CPRIGW)
Raymond Knopp's avatar
 
Raymond Knopp committed
2361 2362

      clock_src = atoi(optarg);
2363

Raymond Knopp's avatar
 
Raymond Knopp committed
2364
      if (clock_src == 0) {
2365 2366 2367 2368 2369
        //  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
2370
      }
2371

Raymond Knopp's avatar
 
Raymond Knopp committed
2372 2373 2374 2375
#else
      printf("Note: -s not defined for ExpressMIMO2\n");
#endif
      break;
2376

2377 2378 2379 2380
    case 'S':
      exit_missed_slots=0;
      printf("Skip exit for missed slots\n");
      break;
2381

2382
    case 'g':
Raymond Knopp's avatar
 
Raymond Knopp committed
2383
      glog_level=atoi(optarg); // value between 1 - 9
2384
      break;
2385 2386

    case 'F':
2387
#ifdef EXMIMO
2388 2389
      sprintf(rxg_fname,"%srxg.lime",optarg);
      rxg_fd = fopen(rxg_fname,"r");
2390

2391
      if (rxg_fd) {
2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409
        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);

2410
#endif
2411
      break;
2412

2413 2414 2415
    case 'G':
      glog_verbosity=atoi(optarg);// value from 0, 0x5, 0x15, 0x35, 0x75
      break;
2416

2417 2418
    case 'x':
      transmission_mode = atoi(optarg);
2419

2420
      if (transmission_mode > 2) {
2421 2422
        printf("Transmission mode > 2 (%d) not supported for the moment\n",transmission_mode);
        exit(-1);
2423
      }
2424
      break;
2425

2426 2427 2428
    case 'T':
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) 
	frame_parms[CC_id]->frame_type = TDD;
2429
      break;
2430

2431 2432 2433 2434
    case 'h':
      help ();
      exit (-1);
       
Raymond Knopp's avatar
 
Raymond Knopp committed
2435
    default:
2436 2437
      help ();
      exit (-1);
Raymond Knopp's avatar
 
Raymond Knopp committed
2438
      break;
2439 2440
    }
  }
2441

Raymond Knopp's avatar
 
Raymond Knopp committed
2442 2443
  if (UE_flag == 0)
    AssertFatal(conf_config_file_name != NULL,"Please provide a configuration file\n");
2444 2445


Raymond Knopp's avatar
 
Raymond Knopp committed
2446
  if ((UE_flag == 0) && (conf_config_file_name != NULL)) {
2447
    int i,j;
2448

Raymond Knopp's avatar
 
Raymond Knopp committed
2449
    NB_eNB_INST = 1;
2450

Raymond Knopp's avatar
 
Raymond Knopp committed
2451 2452
    /* Read eNB configuration file */
    enb_properties = enb_config_init(conf_config_file_name);
2453

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

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

2464 2465
      for (j=0; j<enb_properties->properties[i]->nb_rrh_gw; j++) {
	
2466 2467 2468 2469 2470 2471 2472 2473 2474 2475
	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;
2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492
	  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;
	  } 
2493 2494
	} else {
	  local_remote_radio = BBU_LOCAL_RADIO_HEAD; 
2495 2496 2497 2498
	}
	
      }

2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512
      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
2513 2514
      }

2515

2516
#ifdef OPENAIR2
2517

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

      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");
2531
      }
2532

2533
      init_predef_traffic(enb_properties->properties[i]->num_otg_elements, 1);
2534

2535
#endif
2536

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

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

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

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

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

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

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

2617 2618 2619
  PHY_VARS_UE *UE[MAX_NUM_CCs];

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

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

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

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

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

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

2667
    set_comp_log(HW,      LOG_INFO,  LOG_HIGH, 1);
2668 2669 2670 2671 2672 2673
    set_comp_log(PHY,     LOG_INFO,   LOG_HIGH, 1);
    set_comp_log(MAC,     LOG_INFO,   LOG_HIGH, 1);
    set_comp_log(RLC,     LOG_INFO,   LOG_HIGH, 1);
    set_comp_log(PDCP,    LOG_INFO,   LOG_HIGH, 1);
    set_comp_log(OTG,     LOG_INFO,   LOG_HIGH, 1);
    set_comp_log(RRC,     LOG_INFO,   LOG_HIGH, 1);
2674
#if defined(ENABLE_ITTI)
2675
    set_comp_log(EMU,     LOG_INFO,   LOG_MED, 1);
2676
# if defined(ENABLE_USE_MME)
2677
    set_comp_log(NAS,     LOG_INFO,   LOG_HIGH, 1);
2678 2679
# endif
#endif
2680 2681
  } else {
    printf("configuring for eNB\n");
2682

2683
    set_comp_log(HW,      hw_log_level, hw_log_verbosity, 1);
2684
#ifdef OPENAIR2
2685 2686 2687 2688 2689
    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);

2690
#else
2691
    set_comp_log(PHY,     LOG_INFO,   LOG_HIGH, 1);
2692
#endif
2693 2694 2695 2696
    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);
2697
#if defined(ENABLE_ITTI)
2698
    set_comp_log(EMU,     LOG_INFO,   LOG_MED, 1);
2699
# if defined(ENABLE_USE_MME)
2700 2701 2702 2703
    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);
2704
# endif
2705
#if defined(ENABLE_SECURITY)
2706
    set_comp_log(OSA,    osa_log_level,   osa_log_verbosity, 1);
2707
#endif
2708
#endif
2709
#ifdef LOCALIZATION
2710 2711 2712 2713 2714 2715 2716 2717 2718
    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
2719
    }
2720
  }
2721

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

2729
  if (opp_enabled ==1){
2730
    reset_opp_meas();
2731 2732
  }
  cpuf=get_cpu_freq_GHz();
2733

2734
#if defined(ENABLE_ITTI)
2735

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

Raymond Knopp's avatar
 
Raymond Knopp committed
2742
  itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, itti_dump_file);
2743
 
2744 2745
  // initialize mscgen log after ITTI
  MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX);
2746 2747
#endif
 
2748
#ifdef OPENAIR2
2749

2750 2751
  if (opt_type != OPT_NONE) {
    radio_type_t radio_type;
2752

2753 2754
    if (frame_parms[0]->frame_type == FDD)
      radio_type = RADIO_TYPE_FDD;
2755
    else
2756
      radio_type = RADIO_TYPE_TDD;
2757

2758 2759 2760
    if (init_opt(in_path, in_ip, NULL, radio_type) == -1)
      LOG_E(OPT,"failed to run OPT \n");
  }
2761

2762
#endif
2763
#ifdef PDCP_USE_NETLINK
Raymond Knopp's avatar
 
Raymond Knopp committed
2764
  netlink_init();
2765 2766 2767
#if defined(PDCP_USE_NETLINK_QUEUES)
  pdcp_netlink_init();
#endif
2768 2769
#endif

2770
#if !defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
2771 2772 2773
  // to make a graceful exit when ctrl-c is pressed
  signal(SIGSEGV, signal_handler);
  signal(SIGINT, signal_handler);
2774
#endif
2775 2776

#ifndef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
2777 2778 2779 2780
  check_clock();
#endif

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

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


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

  if (UE_flag==1) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2821 2822 2823
    NB_UE_INST=1;
    NB_INST=1;

Raymond Knopp's avatar
 
Raymond Knopp committed
2824 2825
    PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE**));
    PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_UE*)*MAX_NUM_CCs);
2826 2827

    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
2828 2829 2830 2831

      PHY_vars_UE_g[0][CC_id] = init_lte_UE(frame_parms[CC_id], 0,abstraction_flag,transmission_mode);
      UE[CC_id] = PHY_vars_UE_g[0][CC_id];
      printf("PHY_vars_UE_g[0][%d] = %p\n",CC_id,UE[CC_id]);
Raymond Knopp's avatar
 
Raymond Knopp committed
2832
#ifndef OPENAIR2
2833 2834 2835 2836 2837 2838 2839 2840 2841

      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
2842
      }
2843

2844
#endif
2845 2846 2847


      UE[CC_id]->UE_scan = UE_scan;
2848
      UE[CC_id]->UE_scan_carrier = UE_scan_carrier;
2849 2850 2851
      UE[CC_id]->mode    = mode;

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

2855
      UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1234;
2856
#ifndef OPENAIR2
2857
      UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1235;
2858
#endif
2859

2860
#ifdef EXMIMO
2861

2862 2863 2864 2865
      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
2866
      }
2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885

      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
2886
      }
2887

2888
#else
2889
      UE[CC_id]->rx_total_gain_dB =  (int)rx_gain[CC_id][0];
2890
#endif
2891

2892
      UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id];
2893

2894 2895


2896
#ifdef EXMIMO
2897

Raymond Knopp's avatar
 
Raymond Knopp committed
2898
      //N_TA_offset
2899
      if (UE[CC_id]->lte_frame_parms.frame_type == TDD) {
2900 2901 2902 2903 2904 2905 2906 2907
        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
2908
      }
2909

2910
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
2911
      //already taken care of in lte-softmodem
2912
      UE[CC_id]->N_TA_offset = 0;
2913
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2914
    }
2915

Raymond Knopp's avatar
 
Raymond Knopp committed
2916 2917 2918 2919
    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;
2920 2921 2922



Raymond Knopp's avatar
 
Raymond Knopp committed
2923
    //  printf("tx_max_power = %d -> amp %d\n",tx_max_power,get_tx_amp(tx_max_power,tx_max_power));
2924 2925 2926 2927 2928 2929
  } 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++) {
2930
      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);
2931 2932
      PHY_vars_eNB_g[0][CC_id]->CC_id = CC_id;

2933
#ifndef OPENAIR2
2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949

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

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

#endif

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

2951
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
2952

2953
      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
2954

2955
#else
2956 2957 2958
      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
2959

2960 2961 2962
      // 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
2963

2964
#endif
2965

2966
#ifdef EXMIMO
2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977

      //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
2978
      }
2979

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

2985
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
2986 2987


2988 2989 2990 2991 2992 2993 2994 2995 2996
    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;

  }
2997 2998 2999 3000
#ifndef RTAI
  fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx);
  cpuf=get_cpu_freq_GHz();
#endif 
3001

Raymond Knopp's avatar
 
Raymond Knopp committed
3002
  dump_frame_parms(frame_parms[0]);
3003

3004 3005 3006
  for (card=0; card<MAX_CARDS; card++) {

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

    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
3041

3042 3043 3044 3045 3046 3047
    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;    
    }
3048

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

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

3061
    openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL;
Raymond Knopp's avatar
 
Raymond Knopp committed
3062
#endif
3063

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

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

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

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

3096
      case 25:
3097
        openair0_cfg[card].rx_gain[i] -= 6;
3098 3099
        break;

3100
      case 50:
3101 3102 3103 3104 3105
        openair0_cfg[card].rx_gain[i] -= 3;
        break;

      case 100:
        openair0_cfg[card].rx_gain[i] -= 0;
3106 3107
        break;

3108
      default:
3109
        break;
3110
      }
3111
#endif      
3112

Raymond Knopp's avatar
 
Raymond Knopp committed
3113
    }
3114

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

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

  mac_xface = malloc(sizeof(MAC_xface));

3155
#ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
3156
  int eMBMS_active=0;
3157

Raymond Knopp's avatar
 
Raymond Knopp committed
3158
  l2_init(frame_parms[0],eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL,
3159 3160 3161 3162
          0,// cba_group_active
          0); // HO flag


3163 3164
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3165
  mac_xface->macphy_exit = &exit_fun;
3166

winckel's avatar
winckel committed
3167
#if defined(ENABLE_ITTI)
3168

Raymond Knopp's avatar
 
Raymond Knopp committed
3169
  if (create_tasks(UE_flag ? 0 : 1, UE_flag ? 1 : 0) < 0) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3170
    printf("cannot create ITTI tasks\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3171 3172
    exit(-1); // need a softer mode
  }
3173

Raymond Knopp's avatar
 
Raymond Knopp committed
3174
  printf("ITTI tasks created\n");
winckel's avatar
winckel committed
3175
#endif
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3176 3177

#ifdef OPENAIR2
3178
  if (UE_flag==1) {
3179
    printf("Filling UE band info\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3180
    fill_ue_band_info();
3181
    mac_xface->dl_phy_sync_success (0, 0, 0, 1);
3182
  } else
3183
    mac_xface->mrbch_phy_sync_failure (0, 0, 0);
3184

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3185
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3186

3187
  /* #ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
3188 3189 3190 3191 3192 3193
  //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
3194 3195 3196 3197 3198 3199
  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
3200 3201 3202
  }
  init_predef_traffic(UE_flag ? 1 : 0, UE_flag ? 0 : 1);
  //  }
3203
  #endif */
Raymond Knopp's avatar
 
Raymond Knopp committed
3204

3205
#ifdef EXMIMO
3206
  number_of_cards = openair0_num_detected_cards;
3207 3208
#else
  number_of_cards = 1;
3209
#endif
3210

3211

3212

3213
  for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3214
    rf_map[CC_id].card=0;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3215
    rf_map[CC_id].chain=CC_id+chain_offset;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3216
  }
3217

Raymond Knopp's avatar
 
Raymond Knopp committed
3218 3219
  // connect the TX/RX buffers
  if (UE_flag==1) {
3220
#ifdef OAI_USRP
3221
    openair_daq_vars.timing_advance = timing_advance;
3222
#else
3223
    openair_daq_vars.timing_advance = 160;
3224
#endif
3225
    if (setup_ue_buffers(UE,&openair0_cfg[0],rf_map)!=0) {
3226 3227 3228
      printf("Error setting up eNB buffer\n");
      exit(-1);
    }
3229

3230
    printf("Setting UE buffer to all-RX\n");
3231

3232
    // Set LSBs for antenna switch (ExpressMIMO)
3233
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3234
      for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++)
3235 3236
        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
3237
    }
3238

3239 3240 3241 3242 3243 3244 3245
    if (input_fd) {
      printf("Reading in from file to antenna buffer %d\n",0);
      fread(UE[0]->lte_ue_common_vars.rxdata[0],
	    sizeof(int32_t),
	    frame_parms[0]->samples_per_tti*10,
	    input_fd);
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3246
    //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX;
3247
  } else {
3248
    openair_daq_vars.timing_advance = 0;
3249

3250 3251 3252 3253
    if (setup_eNB_buffers(PHY_vars_eNB_g[0],&openair0_cfg[0],rf_map)!=0) {
      printf("Error setting up eNB buffer\n");
      exit(-1);
    }
3254

3255
    printf("Setting eNB buffer to all-RX\n");
3256

3257
    // Set LSBs for antenna switch (ExpressMIMO)
3258
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3259
      for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++)
3260 3261
        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
3262
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3263
  }
3264

3265
#ifdef EXMIMO
3266
  openair0_config(&openair0_cfg[0],UE_flag);
Raymond Knopp's avatar
 
Raymond Knopp committed
3267 3268
#endif

3269
  /*
Raymond Knopp's avatar
 
Raymond Knopp committed
3270 3271
      for (ant=0;ant<4;ant++)
      p_exmimo_config->rf.do_autocal[ant] = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3272
  */
3273 3274

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3277 3278 3279 3280 3281 3282
  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);
3283
  else
Raymond Knopp's avatar
 
Raymond Knopp committed
3284
    printf("[OPENAIR][SCHED][INIT] Problem creating EMOS FIFO %d, error_code %d\n",CHANSOUNDER_FIFO_MINOR,error_code);
3285

3286 3287
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3288
  mlockall(MCL_CURRENT | MCL_FUTURE);
3289 3290

#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3291
  // make main thread LXRT soft realtime
3292
  /* task = */ rt_task_init_schmod(nam2num("MAIN"), 9, 0, 0, SCHED_FIFO, 0xF);
Raymond Knopp's avatar
 
Raymond Knopp committed
3293 3294 3295 3296 3297

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3300 3301
  pthread_cond_init(&sync_cond,NULL);
  pthread_mutex_init(&sync_mutex, NULL);
3302

3303
  /*  this is moved to the eNB main thread */ 
3304

3305
//#if defined(ENABLE_ITTI)
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3306
  // Wait for eNB application initialization to be complete (eNB registration to MME)
3307 3308 3309 3310 3311
  //  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
3312

Raymond Knopp's avatar
 
Raymond Knopp committed
3313 3314

  // this starts the DMA transfers
3315
#ifdef EXMIMO
3316

Raymond Knopp's avatar
 
Raymond Knopp committed
3317
  if (UE_flag!=1)
3318
    for (card=0; card<openair0_num_detected_cards; card++)
3319
      openair0_start_rt_acquisition(card);
3320

Raymond Knopp's avatar
 
Raymond Knopp committed
3321
#endif
3322 3323

#ifdef XFORMS
3324 3325
  int UE_id;

Raymond Knopp's avatar
 
Raymond Knopp committed
3326 3327
  if (do_forms==1) {
    fl_initialize (&argc, argv, NULL, 0, 0);
3328 3329

    if (UE_flag==0) {
3330
      form_stats_l2 = create_form_stats_form();
3331 3332 3333
      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");
3334 3335

      for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348
	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");
	  }
	}
3349
      }
3350
    } else {
3351 3352 3353 3354 3355 3356 3357
      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
3358
      if (openair_daq_vars.use_ia_receiver) {
3359 3360 3361 3362 3363
        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
3364 3365 3366
      }
    }

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

3369 3370
    if (ret == 0)
      pthread_setname_np( forms_thread, "xforms" );
3371

Raymond Knopp's avatar
 
Raymond Knopp committed
3372 3373
    printf("Scope thread created, ret=%d\n",ret);
  }
3374

3375 3376 3377
#endif

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3378 3379
  ret = pthread_create(&thread3, NULL, emos_thread, NULL);
  printf("EMOS thread created, ret=%d\n",ret);
jiangx's avatar
jiangx committed
3380 3381
  ret = pthread_create(&thread4, NULL, gps_thread, NULL);
  printf("GPS thread created, ret=%d\n",ret);
3382 3383
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3384
  rt_sleep_ns(10*FRAME_PERIOD);
3385 3386

#ifndef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3387
  pthread_attr_init (&attr_dlsch_threads);
3388
  pthread_attr_setstacksize(&attr_dlsch_threads,4*PTHREAD_STACK_MIN);
3389

3390
  pthread_attr_init (&attr_UE_thread);
3391
  pthread_attr_setstacksize(&attr_UE_thread,8192);//5*PTHREAD_STACK_MIN);
3392

3393
#ifndef LOWLATENCY
3394 3395
  sched_param_UE_thread.sched_priority = sched_get_priority_max(SCHED_FIFO);
  pthread_attr_setschedparam(&attr_UE_thread,&sched_param_UE_thread);
3396
  sched_param_dlsch.sched_priority = sched_get_priority_max(SCHED_FIFO); //OPENAIR_THREAD_PRIORITY;
Raymond Knopp's avatar
 
Raymond Knopp committed
3397 3398
  pthread_attr_setschedparam  (&attr_dlsch_threads, &sched_param_dlsch);
  pthread_attr_setschedpolicy (&attr_dlsch_threads, SCHED_FIFO);
3399
  printf("Setting eNB_thread FIFO scheduling policy with priority %d \n", sched_param_dlsch.sched_priority);
3400
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3401

3402 3403
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3404 3405
  // start the main thread
  if (UE_flag == 1) {
3406
    printf("Intializing UE Threads ...\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3407
    init_UE_threads();
3408 3409 3410 3411 3412
#ifdef DLSCH_THREAD
    init_rx_pdsch_thread();
    rt_sleep_ns(FRAME_PERIOD/10);
    init_dlsch_threads();
#endif
3413

3414
    sleep(1);
3415
#ifdef RTAI
3416
    main_ue_thread = rt_thread_create(UE_thread, NULL, 100000000);
3417
#else
3418
    error_code = pthread_create(&main_ue_thread, &attr_UE_thread, UE_thread, NULL);
3419

Raymond Knopp's avatar
 
Raymond Knopp committed
3420 3421 3422
    if (error_code!= 0) {
      LOG_D(HW,"[lte-softmodem.c] Could not allocate UE_thread, error %d\n",error_code);
      return(error_code);
3423
    } else {
3424 3425
      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
3426
    }
3427

3428
#endif
3429
    printf("UE threads created\n");
3430 3431 3432 3433 3434 3435 3436 3437 3438 3439
#ifdef USE_MME

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

#endif



3440
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
3441 3442
    if (multi_thread>0) {
      init_eNB_proc();
3443
      sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3444 3445
      LOG_D(HW,"[lte-softmodem.c] eNB threads created\n");
    }
3446

3447
    printf("Creating main eNB_thread \n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3448
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3449
    main_eNB_thread = rt_thread_create(eNB_thread, NULL, PTHREAD_STACK_MIN);
Raymond Knopp's avatar
 
Raymond Knopp committed
3450
#else
3451
    error_code = pthread_create( &main_eNB_thread, &attr_dlsch_threads, eNB_thread, NULL );
3452

Raymond Knopp's avatar
 
Raymond Knopp committed
3453 3454 3455
    if (error_code!= 0) {
      LOG_D(HW,"[lte-softmodem.c] Could not allocate eNB_thread, error %d\n",error_code);
      return(error_code);
3456
    } else {
3457 3458
      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
3459
    }
3460

Raymond Knopp's avatar
 
Raymond Knopp committed
3461 3462
#endif
  }
3463

Raymond Knopp's avatar
 
Raymond Knopp committed
3464
  // Sleep to allow all threads to setup
Raymond Knopp's avatar
 
Raymond Knopp committed
3465
  sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3466

3467

3468

3469
#ifndef EXMIMO
3470

Raymond Knopp's avatar
 
Raymond Knopp committed
3471
#ifndef USRP_DEBUG
3472
  if (mode!=loop_through_memory)
navid's avatar
navid committed
3473 3474 3475
    if (openair0.trx_start_func(&openair0) != 0 ) 
      LOG_E(HW,"Could not start the device\n");

Raymond Knopp's avatar
 
Raymond Knopp committed
3476
#endif
3477

3478 3479
#endif

3480
  printf("Sending sync to all threads\n");
3481

Raymond Knopp's avatar
 
Raymond Knopp committed
3482
  pthread_mutex_lock(&sync_mutex);
3483
  sync_var=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3484 3485
  pthread_cond_broadcast(&sync_cond);
  pthread_mutex_unlock(&sync_mutex);
3486

Raymond Knopp's avatar
 
Raymond Knopp committed
3487 3488 3489
  // wait for end of program
  printf("TYPE <CTRL-C> TO TERMINATE\n");
  //getchar();
3490 3491

#if defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
3492 3493
  printf("Entering ITTI signals handler\n");
  itti_wait_tasks_end();
3494
  oai_exit=1;
3495
#else
3496

Raymond Knopp's avatar
 
Raymond Knopp committed
3497 3498
  while (oai_exit==0)
    rt_sleep_ns(FRAME_PERIOD);
3499

3500
#endif
3501

3502 3503 3504 3505 3506
  write_output("pusch_rb.m","puschrb",PHY_vars_eNB_g[0][0]->pusch_stats_rb,10240,1,2);
  write_output("pusch_mcs.m","puschmcs",PHY_vars_eNB_g[0][0]->pusch_stats_mcs,10240,1,2);
  write_output("pusch_round.m","puschround",PHY_vars_eNB_g[0][0]->pusch_stats_round,10240,1,2);
  write_output("pusch_bsr.m","puschbsr",PHY_vars_eNB_g[0][0]->pusch_stats_bsr,10240,1,2);
  write_output("pusch_BO.m","puschBO",PHY_vars_eNB_g[0][0]->pusch_stats_BO,10240,1,2);
Raymond Knopp's avatar
 
Raymond Knopp committed
3507
  // stop threads
3508
#ifdef XFORMS
Raymond Knopp's avatar
 
Raymond Knopp committed
3509
  printf("waiting for XFORMS thread\n");
3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523

  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++) {
3524 3525 3526 3527
	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
3528
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
3529
    }
3530 3531
  }

3532 3533
#endif

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3536 3537
  // cleanup
  if (UE_flag == 1) {
3538
#ifdef EXMIMO
3539
#ifdef RTAI
3540
    rt_thread_join(main_ue_thread);
3541
#else
3542
    pthread_join(main_ue_thread,&status);
3543 3544
#endif
#ifdef DLSCH_THREAD
Raymond Knopp's avatar
 
Raymond Knopp committed
3545 3546
    cleanup_dlsch_threads();
    cleanup_rx_pdsch_thread();
3547
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3548
#endif
3549
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
3550
#ifdef DEBUG_THREADS
Raymond Knopp's avatar
 
Raymond Knopp committed
3551
    printf("Joining eNB_thread ...");
Raymond Knopp's avatar
 
Raymond Knopp committed
3552
#endif
3553
#ifdef RTAI
3554
    rt_thread_join(main_eNB_thread);
3555
#else
3556 3557
    int *eNB_thread_status_p;
    int result = pthread_join( main_eNB_thread, (void**)&eNB_thread_status_p );
Raymond Knopp's avatar
 
Raymond Knopp committed
3558
#ifdef DEBUG_THREADS
3559

3560
    if (result != 0) {
3561
      printf( "\nError joining main_eNB_thread.\n" );
3562
    } else {
3563 3564 3565 3566 3567
      if (eNB_thread_status_p) {
        printf( "status %d\n", *eNB_thread_status_p );
      } else {
        printf( "The thread was killed. No status available.\n");
      }
3568
    }
3569

3570 3571
#else
    UNUSED(result);
3572 3573
#endif // DEBUG_THREADS
#endif // RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3574

Raymond Knopp's avatar
 
Raymond Knopp committed
3575 3576 3577
    if (multi_thread>0) {
      printf("Killing eNB processing threads\n");
      kill_eNB_proc();
Raymond Knopp's avatar
 
Raymond Knopp committed
3578
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3579
  }
3580

3581
#ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
3582
  //cleanup_pdcp_thread();
3583 3584
#endif

3585
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3586
  stop_rt_timer();
3587
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3588 3589
  pthread_cond_destroy(&sync_cond);
  pthread_mutex_destroy(&sync_mutex);
3590

3591

3592
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3593
  printf("stopping card\n");
3594
  openair0_stop(0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3595 3596
  printf("closing openair0_lib\n");
  openair0_close();
navid's avatar
navid committed
3597 3598
#else
  openair0.trx_end_func(&openair0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3599
#endif
3600 3601

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3602 3603 3604
  printf("waiting for EMOS thread\n");
  pthread_cancel(thread3);
  pthread_join(thread3,&status);
jiangx's avatar
jiangx committed
3605 3606 3607
  printf("waiting for GPS thread\n");
  pthread_cancel(thread4);
  pthread_join(thread4,&status);
3608 3609 3610
#endif

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3611 3612
  error_code = rtf_destroy(CHANSOUNDER_FIFO_MINOR);
  printf("[OPENAIR][SCHED][CLEANUP] EMOS FIFO closed, error_code %d\n", error_code);
3613 3614
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3615
  if (ouput_vcd)
3616
    VCD_SIGNAL_DUMPER_CLOSE();
3617

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3618
#ifdef OPENAIR2
3619

3620
  if (opt_enabled == 1)
3621
    terminate_opt();
3622

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3623
#endif
3624

Raymond Knopp's avatar
 
Raymond Knopp committed
3625
  logClean();
3626

Raymond Knopp's avatar
 
Raymond Knopp committed
3627 3628
  return 0;
}
3629 3630


3631 3632 3633
/* 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
3634
   antennas are mapped to successive RF chains on the same card. */
3635 3636
int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs])
{
3637

3638
  int i, CC_id;
3639
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3640
  uint16_t N_TA_offset = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3641 3642
#else
  int j;
Raymond Knopp's avatar
 
Raymond Knopp committed
3643
#endif
3644
  LTE_DL_FRAME_PARMS *frame_parms;
3645

Raymond Knopp's avatar
 
Raymond Knopp committed
3646

3647 3648
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    if (phy_vars_eNB[CC_id]) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3649 3650
      frame_parms = &(phy_vars_eNB[CC_id]->lte_frame_parms);
      printf("setup_eNB_buffers: frame_parms = %p\n",frame_parms);
3651
    } else {
3652 3653
      printf("phy_vars_eNB[%d] not initialized\n", CC_id);
      return(-1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3654
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3655

3656
#ifndef EXMIMO
3657

3658 3659
    if (frame_parms->frame_type == TDD) {
      if (frame_parms->N_RB_DL == 100)
3660
        N_TA_offset = 624;
3661
      else if (frame_parms->N_RB_DL == 50)
3662
        N_TA_offset = 624/2;
3663
      else if (frame_parms->N_RB_DL == 25)
3664
        N_TA_offset = 624/4;
Raymond Knopp's avatar
 
Raymond Knopp committed
3665
    }
3666

Raymond Knopp's avatar
 
Raymond Knopp committed
3667
#endif
3668

Raymond Knopp's avatar
 
Raymond Knopp committed
3669
    // replace RX signal buffers with mmaped HW versions
3670
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3671 3672 3673
    openair0_cfg[CC_id].tx_num_channels = 0;
    openair0_cfg[CC_id].rx_num_channels = 0;

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

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

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

      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;
3693
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
3694
    }
3695 3696

    for (i=0; i<frame_parms->nb_antennas_tx; i++) {
3697 3698 3699
      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];
3700

3701
      if (openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i]) {
3702 3703 3704 3705 3706 3707
        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++;
3708
      }
3709

3710
      printf("txdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3711 3712 3713 3714

      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;
3715
      }
3716
    }
3717

3718
#else // not EXMIMO
3719 3720 3721
    rxdata = (int32_t**)malloc16(frame_parms->nb_antennas_rx*sizeof(int32_t*));
    txdata = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*));

3722
    for (i=0; i<frame_parms->nb_antennas_rx; i++) {
3723
      free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]);
3724
      rxdata[i] = (int32_t*)(32 + malloc16(32+openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation
3725
      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
3726
      memset(rxdata[i], 0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t));
3727
      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);
3728
      
Raymond Knopp's avatar
 
Raymond Knopp committed
3729
    }
3730 3731

    for (i=0; i<frame_parms->nb_antennas_tx; i++) {
3732
      free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3733
      txdata[i] = (int32_t*)(32 + malloc16(32 + openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation
3734
      phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i] = txdata[i];
3735
      memset(txdata[i],0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t));
3736
      printf("txdata[%d] @ %p\n", i, phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3737

Raymond Knopp's avatar
 
Raymond Knopp committed
3738
    }
3739

Raymond Knopp's avatar
 
Raymond Knopp committed
3740
#endif
3741
  }
3742

3743
  return(0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3744
}
3745

3746
void reset_opp_meas(void) {
3747 3748 3749
  int sfn;
  reset_meas(&softmodem_stats_mt);
  reset_meas(&softmodem_stats_hw);
3750
  
3751 3752 3753 3754 3755 3756
  for (sfn=0; sfn < 10; sfn++) {
    reset_meas(&softmodem_stats_tx_sf[sfn]);
    reset_meas(&softmodem_stats_rx_sf[sfn]);
  }
}

3757 3758
void print_opp_meas(void) {

3759 3760 3761
  int sfn=0;
  print_meas(&softmodem_stats_mt, "Main ENB Thread", NULL, NULL);
  print_meas(&softmodem_stats_hw, "HW Acquisation", NULL, NULL);
3762
  
3763 3764 3765 3766 3767
  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);
  }
}
3768 3769