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

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


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

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

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

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

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

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

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

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

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

#include "PHY/types.h"
66

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

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

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

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

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

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

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

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

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

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

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

#define FRAME_PERIOD    100000000ULL
#define DAQ_PERIOD      66667ULL

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

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

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


Raymond Knopp's avatar
 
Raymond Knopp committed
147

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

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

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

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

#ifdef RTAI
171

172 173
static long                      main_eNB_thread;
static long                      main_ue_thread;
174

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

179
pthread_attr_t                  attr_dlsch_threads;
180 181
pthread_attr_t                  attr_UE_thread;

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

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

191

192 193


194
struct sched_param              sched_param_UE_thread;
195

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
212

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

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

223

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
234

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

238
static char                     threequarter_fs=0;
239

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

243
openair0_rf_map rf_map[MAX_NUM_CCs];
244

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

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

254 255
FILE *input_fd=NULL;

256

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

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

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

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

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

#endif
301 302

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
325

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

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_eNB_ip[20] = "127.0.0.1";
Raymond Knopp's avatar
Raymond Knopp committed
366
int rrh_eNB_port = 50000;
Raymond Knopp's avatar
 
Raymond Knopp committed
367
char *rrh_UE_ip = "127.0.0.1";
368
int rrh_UE_port = 51000;
Raymond Knopp's avatar
 
Raymond Knopp committed
369 370 371
#endif

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

375
unsigned int build_rflocal(int txi, int txq, int rxi, int rxq)
376
{
Raymond Knopp's avatar
 
Raymond Knopp committed
377
  return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
378 379 380
}
unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
381
  return (dcoff_i_rxfe + (dcoff_q_rxfe<<8));
382 383
}

384
#if !defined(ENABLE_ITTI)
385 386 387 388 389 390 391 392
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);
393

394 395 396 397
    // print out all the frames to stderr
    fprintf(stderr, "Error: signal %d:\n", sig);
    backtrace_symbols_fd(array, size, 2);
    exit(-1);
398 399
  } else {
    printf("trying to exit gracefully...\n");
400
    oai_exit = 1;
401 402
  }
}
403
#endif
404 405 406 407 408 409 410 411 412 413 414 415 416 417 418
#define KNRM  "\x1B[0m"
#define KRED  "\x1B[31m"
#define KGRN  "\x1B[32m"
#define KBLU  "\x1B[34m"
#define RESET "\033[0m"

void help (void) {
  printf (KGRN "Usage:\n");
  printf("  sudo -E lte-softmodem [options]\n");
  printf("  sudo -E ./lte-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.openEPC.conf -S -V -m 26 -t 16 -x 1 --ulsch-max-errors 100 -W\n\n");
  printf("Options:\n");
  printf("  --ulsch-max-errors set the max ULSCH erros\n");
  printf("  --calib-ue-rx set UE RX calibration\n");
  printf("  --calib-ue-rx-med \n");
  printf("  --calib-ue-rxbyp\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
419 420
  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");
421
  printf("  --no-L2-connect bypass L2 and upper layers\n");
422 423 424 425
  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");
426
  printf("  -C Set the downlink frequency for all component carriers\n");
427 428 429
  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");
430
  printf("  -G Set the global log verbosity \n");
431 432 433 434 435 436
  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("  -M IP address of RRH\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
437
  printf("  -r Set the PRB, valid values: 6, 25, 50, 100  \n");    
438 439
  printf("  -S Skip the missed slots/subframes \n");    
  printf("  -t Set the maximum uplink MCS\n");
440
  printf("  -T Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n");
441 442 443 444
  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);    
445

446
}
447 448
void exit_fun(const char* s)
{
449
  if (s != NULL) {
450
    printf("%s %s() Exiting OAI softmodem: %s\n",__FILE__, __FUNCTION__, s);
451 452 453 454 455
  }

  oai_exit = 1;

#if defined(ENABLE_ITTI)
Florian Kaltenberger's avatar
Florian Kaltenberger committed
456
  sleep(1); //allow lte-softmodem threads to exit first
457
  itti_terminate_tasks (TASK_UNKNOWN);
458
#endif
459 460 461 462 463 464

  //rt_sleep_ns(FRAME_PERIOD);

  //exit (-1);
}

465

466
#ifdef XFORMS
467

468 469
void reset_stats(FL_OBJECT *button, long arg)
{
470 471
  int i,j,k;
  PHY_VARS_eNB *phy_vars_eNB = PHY_vars_eNB_g[0][0];
472 473 474 475 476 477 478

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

481 482 483
      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;
484 485 486 487 488 489

      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;
490
      }
491
    }
492

493 494 495
    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;
496 497 498
  }
}

499 500
static void *scope_thread(void *arg)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
501
  char stats_buffer[16384];
502
# ifdef ENABLE_XFORMS_WRITE_STATS
Raymond Knopp's avatar
 
Raymond Knopp committed
503
  FILE *UE_stats, *eNB_stats;
504
# endif
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
505
  int len = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
506
  struct sched_param sched_param;
507
  int UE_id, CC_id;
508

509
  sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
Raymond Knopp's avatar
 
Raymond Knopp committed
510
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
511

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

514
# ifdef ENABLE_XFORMS_WRITE_STATS
515 516

  if (UE_flag==1)
Raymond Knopp's avatar
 
Raymond Knopp committed
517
    UE_stats  = fopen("UE_stats.txt", "w");
518
  else
Raymond Knopp's avatar
 
Raymond Knopp committed
519
    eNB_stats = fopen("eNB_stats.txt", "w");
520

521
#endif
522

Raymond Knopp's avatar
 
Raymond Knopp committed
523 524
  while (!oai_exit) {
    if (UE_flag==1) {
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
525
      len = dump_ue_stats (PHY_vars_UE_g[0][0], stats_buffer, 0, mode,rx_input_level_dBm);
knopp's avatar
knopp committed
526 527 528
      //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);
529

530 531 532 533 534
      phy_scope_UE(form_ue[0],
                   PHY_vars_UE_g[0][0],
                   0,
                   0,7);

Raymond Knopp's avatar
 
Raymond Knopp committed
535
    } else {
536 537 538 539 540 541
      if (PHY_vars_eNB_g[0][0]->mac_enabled==1) {
	len = dump_eNB_l2_stats (stats_buffer, 0);
	//fl_set_object_label(form_stats_l2->stats_text, stats_buffer);
	fl_clear_browser(form_stats_l2->stats_text);
	fl_add_browser_line(form_stats_l2->stats_text, stats_buffer);
      }
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
542
      len = dump_eNB_stats (PHY_vars_eNB_g[0][0], stats_buffer, 0);
543

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

547 548 549
      //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);
550

551
      for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
552 553 554 555 556
	for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
	  phy_scope_eNB(form_enb[CC_id][UE_id],
			PHY_vars_eNB_g[0][CC_id],
			UE_id);
	}
Raymond Knopp's avatar
 
Raymond Knopp committed
557
      }
558

559
    }
560

Raymond Knopp's avatar
 
Raymond Knopp committed
561
    //printf("doing forms\n");
Florian Kaltenberger's avatar
Florian Kaltenberger committed
562 563
    //usleep(100000); // 100 ms
    sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
564
  }
565

566
  //  printf("%s",stats_buffer);
567

568
# ifdef ENABLE_XFORMS_WRITE_STATS
569

570 571 572 573 574 575
  if (UE_flag==1) {
    if (UE_stats) {
      rewind (UE_stats);
      fwrite (stats_buffer, 1, len, UE_stats);
      fclose (UE_stats);
    }
576
  } else {
577 578 579 580 581 582
    if (eNB_stats) {
      rewind (eNB_stats);
      fwrite (stats_buffer, 1, len, eNB_stats);
      fclose (eNB_stats);
    }
  }
583

584
# endif
585

Raymond Knopp's avatar
 
Raymond Knopp committed
586
  pthread_exit((void*)arg);
587 588 589 590 591 592
}
#endif

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

jiangx's avatar
jiangx committed
593 594 595 596 597 598 599 600
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;

601
  sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
jiangx's avatar
jiangx committed
602
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
603

jiangx's avatar
jiangx committed
604 605 606
  printf("GPS thread has priority %d\n",sched_param.sched_priority);

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

jiangx's avatar
jiangx committed
608 609
#if GPSD_API_MAJOR_VERSION>=5
  ret = gps_open("127.0.0.1","2947",gps_data_ptr);
610

jiangx's avatar
jiangx committed
611 612 613
  if (ret!=0)
#else
  gps_data_ptr = gps_open("127.0.0.1","2947");
614 615

  if (gps_data_ptr == NULL)
jiangx's avatar
jiangx committed
616
#endif
617 618 619 620 621
  {
    printf("[EMOS] Could not open GPS\n");
    pthread_exit((void*)arg);
  }

jiangx's avatar
jiangx committed
622 623 624 625 626
#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
627 628 629 630
  {
    printf("[EMOS] Error sending command to GPS\n");
    pthread_exit((void*) arg);
  } else
jiangx's avatar
jiangx committed
631 632
    printf("[EMOS] Opened GPS, gps_data=%p\n", gps_data_ptr);

633 634 635

  while (!oai_exit) {
    printf("[EMOS] polling data from gps\n");
jiangx's avatar
jiangx committed
636
#if GPSD_API_MAJOR_VERSION>=5
637 638 639

    if (gps_waiting(gps_data_ptr,500)) {
      if (gps_read(gps_data_ptr) <= 0) {
jiangx's avatar
jiangx committed
640
#else
641 642 643 644 645 646 647 648

    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
649
      }
650 651 652 653 654 655 656 657
    } //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
658 659 660 661 662

  pthread_exit((void*) arg);

}

663 664 665 666 667 668 669 670 671 672 673
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;
674

jiangx's avatar
jiangx committed
675
  int channel_buffer_size,ret;
676

677 678 679
  time_t timer;
  struct tm *now;

680
  struct sched_param sched_param;
681 682

  sched_param.sched_priority = sched_get_priority_max(SCHED_FIFO)-1;
683
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
684

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

687 688 689 690 691 692 693 694 695 696 697 698
  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;

699 700 701 702
  if (fifo2file_buffer == NULL) {
    printf("[EMOS] Cound not allocate memory for fifo2file_buffer\n");
    exit(EXIT_FAILURE);
  }
703

704 705 706 707
  if ((fifo = open(CHANSOUNDER_FIFO_DEV, O_RDONLY)) < 0) {
    fprintf(stderr, "[EMOS] Error opening the fifo\n");
    exit(EXIT_FAILURE);
  }
708 709 710 711 712


  time(&starttime_tmp);
  localtime_r(&starttime_tmp,&starttime);
  snprintf(dumpfile_name,1024,"/tmp/%s_data_%d%02d%02d_%02d%02d%02d.EMOS",
713 714
           (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);
715 716

  dumpfile_id = fopen(dumpfile_name,"w");
717 718 719 720 721

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


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

726 727 728 729 730 731 732
  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);
733

734 735 736 737
    if (bytes<=0) {
      usleep(100);
      continue;
    }
738

739 740 741
    if (bytes != channel_buffer_size) {
      printf("[EMOS] ERROR! Only got %d bytes instead of %d!\n",bytes,channel_buffer_size);
    }
742

743 744 745 746 747 748
    /*
    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);
    */
749

750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770
    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
771

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

779 780 781
  free(fifo2file_buffer);
  fclose(dumpfile_id);
  close(fifo);
782

783 784 785 786 787
  pthread_exit((void*) arg);

}
#endif

788 789


790
#if defined(ENABLE_ITTI)
791 792 793 794 795
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[] = {".    ", "..   ", "...  ", ".... ", ".....",
796 797
                                " ....", "  ...", "   ..", "    .", "     "
                               };
798 799 800 801
    int i = 0;

    while ((!oai_exit) && (*start_flag == 0)) {
      LOG_N(EMU, message, indicator[i]);
802
      fflush(stdout);
803 804 805
      i = (i + 1) % (sizeof(indicator) / sizeof(indicator[0]));
      usleep(200000);
    }
806

807 808 809 810 811
    LOG_D(EMU,"\n");
  }
}
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
812
#if defined(ENABLE_ITTI)
813
void *l2l1_task(void *arg)
814
{
Raymond Knopp's avatar
 
Raymond Knopp committed
815 816 817 818 819
  MessageDef *message_p = NULL;
  int         result;

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
820

Raymond Knopp's avatar
 
Raymond Knopp committed
821 822
  if (UE_flag == 0) {
    /* Wait for the initialize message */
823
    printf("Wait for the ITTI initialize message\n");
824
    do {
Raymond Knopp's avatar
 
Raymond Knopp committed
825
      if (message_p != NULL) {
826 827
        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
828
      }
829

830 831 832
      itti_receive_msg (TASK_L2L1, &message_p);

      switch (ITTI_MSG_ID(message_p)) {
Raymond Knopp's avatar
 
Raymond Knopp committed
833
      case INITIALIZE_MESSAGE:
834 835 836 837
        /* 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
838 839

      case TERMINATE_MESSAGE:
840 841 842 843
        printf("received terminate message\n");
        oai_exit=1;
        itti_exit_task ();
        break;
Raymond Knopp's avatar
 
Raymond Knopp committed
844 845

      default:
846 847
        LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
        break;
848
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
849
    } while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE);
850

Raymond Knopp's avatar
 
Raymond Knopp committed
851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871
    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;
872

Raymond Knopp's avatar
 
Raymond Knopp committed
873 874 875 876 877 878 879 880 881 882 883
    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);
884
  } while(!oai_exit);
885

Raymond Knopp's avatar
 
Raymond Knopp committed
886
  return NULL;
887 888 889
}
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
890

891 892
void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
893 894 895 896

  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
897
  int slot_sizeF = (phy_vars_eNB->lte_frame_parms.ofdm_symbol_size)*
898
                   ((phy_vars_eNB->lte_frame_parms.Ncp==1) ? 6 : 7);
899
  int len;
Raymond Knopp's avatar
 
Raymond Knopp committed
900 901

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
909

Raymond Knopp's avatar
 
Raymond Knopp committed
910
    for (aa=0; aa<phy_vars_eNB->lte_frame_parms.nb_antennas_tx; aa++) {
911 912 913
      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,
914
                     phy_vars_eNB->lte_frame_parms.ofdm_symbol_size,
915 916 917 918 919
                     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),
920
                     phy_vars_eNB->lte_frame_parms.ofdm_symbol_size,
921 922 923 924 925 926 927 928
                     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));
929 930 931 932 933 934
	// 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
935
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
936

937 938 939 940 941 942 943
      // if S-subframe generate first slot only
      if (subframe_select(&phy_vars_eNB->lte_frame_parms,subframe) == SF_S)
	len = phy_vars_eNB->lte_frame_parms.samples_per_tti>>1;
      else
	len = phy_vars_eNB->lte_frame_parms.samples_per_tti;
 
     for (i=0; i<len; i++) {
944 945 946 947 948 949 950 951 952
        tx_offset = (int)slot_offset+time_offset[aa]+i;

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

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

        ((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[0]=
Raymond Knopp's avatar
 
Raymond Knopp committed
953
#ifdef EXMIMO
954
          ((short*)dummy_tx_b)[2*i]<<4;
kaltenbe's avatar
kaltenbe committed
955
#elif OAI_BLADERF
956
	((short*)dummy_tx_b)[2*i];
Raymond Knopp's avatar
 
Raymond Knopp committed
957
#else
958
          ((short*)dummy_tx_b)[2*i]<<4;
Raymond Knopp's avatar
 
Raymond Knopp committed
959
#endif
960
	  ((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[1]=
Raymond Knopp's avatar
 
Raymond Knopp committed
961
#ifdef EXMIMO
962
	    ((short*)dummy_tx_b)[2*i+1]<<4;
kaltenbe's avatar
kaltenbe committed
963
#elif OAI_BLADERF
964
	  ((short*)dummy_tx_b)[2*i+1];
Raymond Knopp's avatar
 
Raymond Knopp committed
965
#else
966
	  ((short*)dummy_tx_b)[2*i+1]<<4;
Raymond Knopp's avatar
 
Raymond Knopp committed
967
#endif
968 969 970 971 972 973 974
     }
     // 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;
       }
     }
975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993

     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
994 995 996 997
    }
  }
}

998 999 1000 1001 1002 1003 1004 1005 1006
/* 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
1007

1008 1009 1010 1011 1012 1013 1014 1015 1016
/*!
 * \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
1017 1018

  eNB_proc_t *proc = (eNB_proc_t*)param;
1019 1020
  FILE  *tx_time_file;
  char tx_time_name[101];
kaltenbe's avatar
kaltenbe committed
1021

1022 1023 1024 1025
  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");
  }
1026 1027 1028
  // set default return value
  eNB_thread_tx_status[proc->subframe] = 0;

1029 1030
  MSC_START_USE();

Raymond Knopp's avatar
 
Raymond Knopp committed
1031 1032
#ifdef RTAI
  RT_TASK *task;
1033
  char task_name[8];
Raymond Knopp's avatar
 
Raymond Knopp committed
1034

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

1038 1039 1040
  if (task == NULL) {
    LOG_E(PHY,"[SCHED][eNB] Problem starting eNB_proc_TX thread_index %d (%s)!!!!\n",proc->subframe,task_name);
    return 0;
1041 1042 1043 1044 1045
  } else {
    LOG_I(PHY,"[SCHED][eNB] eNB TX thread CC %d SF %d started with id %p\n",
          proc->CC_id,
          proc->subframe,
          task);
1046
  }
1047

Raymond Knopp's avatar
 
Raymond Knopp committed
1048
#else
1049
#ifdef LOWLATENCY
1050 1051
  struct sched_attr attr;
  unsigned int flags = 0;
navid's avatar
navid committed
1052 1053 1054 1055 1056 1057 1058
  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; 
  }
1059

1060 1061 1062 1063
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1064

navid's avatar
navid committed
1065 1066 1067 1068
  attr.sched_policy   = SCHED_DEADLINE;
  attr.sched_runtime  = runtime;
  attr.sched_deadline = deadline;
  attr.sched_period   = period; 
1069

1070 1071 1072 1073
  if (sched_setattr(0, &attr, flags) < 0 ) {
    perror("[SCHED] eNB tx thread: sched_setattr failed\n");
    return &eNB_thread_tx_status[proc->subframe];
  }
1074

navid's avatar
navid committed
1075
  LOG_I( HW, "[SCHED] eNB TX deadline thread %d(TID %ld) started on CPU %d\n", proc->subframe, gettid(), sched_getcpu() );
1076
#else
1077
  LOG_I( HW, "[SCHED][eNB] TX thread %d started on CPU %d TID %d\n", proc->subframe, sched_getcpu(),gettid() );
1078 1079
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
1080 1081 1082 1083 1084 1085 1086 1087
#endif

  mlockall(MCL_CURRENT | MCL_FUTURE);

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

1088
  while (!oai_exit) {
1089

1090
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe), 0 );
1091

1092
    if (pthread_mutex_lock(&proc->mutex_tx) != 0) {
1093
      LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc %d\n", proc->subframe );
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1094
      exit_fun("nothing to add");
1095
      break;
1096
    }
1097

1098
    while (proc->instance_cnt_tx < 0) {
1099 1100 1101
      // 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
1102
    }
1103

1104 1105 1106 1107 1108
    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
1109

1110 1111
    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 );
1112 1113 1114
    start_meas( &softmodem_stats_tx_sf[proc->subframe] );

    if (oai_exit) break;
1115

1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127
    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;
      }
1128 1129
      /* wait for our turn or oai_exit */
      while (sync_phy_proc[proc->subframe].phy_proc_CC_id != proc->CC_id && !oai_exit) {
1130 1131 1132
        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
1133

1134 1135 1136
      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");
1137 1138
      }

1139 1140 1141
      if (oai_exit)
        break;

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

1144
      /* we're done, let the next one proceed */
1145 1146 1147 1148 1149
      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;
      }
1150 1151 1152 1153
      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) {
1154
        LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc %d\n", proc->subframe);
1155 1156 1157
        exit_fun("nothing to add");
        break;
      }
1158
    }
1159

1160
    do_OFDM_mod_rt( proc->subframe_tx, PHY_vars_eNB_g[0][proc->CC_id] );
kaltenbe's avatar
kaltenbe committed
1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174
    /*
    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;
    }
    */
1175 1176 1177 1178 1179
    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
1180

1181 1182 1183 1184 1185 1186 1187 1188 1189
    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++;
1190

1191 1192
    if (proc->frame_tx==1024)
      proc->frame_tx=0;
1193
    stop_meas( &softmodem_stats_tx_sf[proc->subframe] );
1194 1195 1196 1197 1198 1199 1200
#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 
1201 1202
    print_meas_now(&softmodem_stats_tx_sf[proc->subframe],"eNB_TX_SF",proc->subframe, tx_time_file);

1203 1204
  }

1205 1206


1207
  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
1208

Raymond Knopp's avatar
 
Raymond Knopp committed
1209 1210 1211
#ifdef HARD_RT
  rt_make_soft_real_time();
#endif
1212

Raymond Knopp's avatar
 
Raymond Knopp committed
1213
#ifdef DEBUG_THREADS
1214
  printf( "Exiting eNB thread TX %d\n", proc->subframe );
Raymond Knopp's avatar
 
Raymond Knopp committed
1215 1216 1217 1218 1219
#endif
  // clean task
#ifdef RTAI
  rt_task_delete(task);
#endif
1220

1221 1222
  eNB_thread_tx_status[proc->subframe] = 0;
  return &eNB_thread_tx_status[proc->subframe];
Raymond Knopp's avatar
 
Raymond Knopp committed
1223 1224 1225
}


1226 1227 1228 1229 1230 1231 1232 1233 1234 1235
/*!
 * \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
1236
  eNB_proc_t *proc = (eNB_proc_t*)param;
1237

1238 1239
  FILE  *rx_time_file;
  char rx_time_name[101];
Raymond Knopp's avatar
 
Raymond Knopp committed
1240 1241
  int i;

1242 1243 1244 1245
  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");
  }
1246 1247 1248
  // set default return value
  eNB_thread_rx_status[proc->subframe] = 0;

1249 1250
  MSC_START_USE();

Raymond Knopp's avatar
 
Raymond Knopp committed
1251 1252
#ifdef RTAI
  RT_TASK *task;
1253
  char task_name[8];
Raymond Knopp's avatar
 
Raymond Knopp committed
1254

1255
  sprintf(task_name,"RXC%1dS%1d",proc->CC_id,proc->subframe);
Raymond Knopp's avatar
 
Raymond Knopp committed
1256 1257 1258
  task = rt_task_init_schmod(nam2num(task_name), 0, 0, 0, SCHED_FIFO, 0xF);

  if (task==NULL) {
1259 1260
    LOG_E(PHY,"[SCHED][eNB] Problem starting eNB_proc_RX thread_index %d (%s)!!!!\n",proc->subframe,task_name);
    return 0;
1261
  } else {
1262
    LOG_I(PHY,"[SCHED][eNB] eNB RX thread CC_id %d SF %d started with id %p\n", /*  on CPU %d*/
1263 1264 1265
          proc->CC_id,
          proc->subframe,
          task); /*,rtai_cpuid()*/
Raymond Knopp's avatar
 
Raymond Knopp committed
1266
  }
1267

Raymond Knopp's avatar
 
Raymond Knopp committed
1268
#else
1269
#ifdef LOWLATENCY
1270 1271
  struct sched_attr attr;
  unsigned int flags = 0;
navid's avatar
navid committed
1272 1273 1274 1275 1276 1277 1278 1279
  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;
  }
1280

1281 1282 1283 1284
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1285

1286
  attr.sched_policy = SCHED_DEADLINE;
navid's avatar
navid committed
1287 1288 1289
  attr.sched_runtime  = runtime;
  attr.sched_deadline = deadline;
  attr.sched_period   = period; 
1290 1291

  if (sched_setattr(0, &attr, flags) < 0 ) {
1292
    perror("[SCHED] eNB RX sched_setattr failed\n");
1293
    return &eNB_thread_rx_status[proc->subframe];
1294
  }
1295

1296
  LOG_I( HW, "[SCHED] eNB RX deadline thread %d(TID %ld) started on CPU %d\n", proc->subframe, gettid(), sched_getcpu() );
1297
#else
1298
  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
1299
#endif
1300
#endif // RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
1301 1302 1303 1304 1305 1306 1307

  mlockall(MCL_CURRENT | MCL_FUTURE);

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

1308
  while (!oai_exit) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1309

1310
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 0 );
1311

Raymond Knopp's avatar
 
Raymond Knopp committed
1312
    if (pthread_mutex_lock(&proc->mutex_rx) != 0) {
1313 1314 1315
      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
1316 1317
    }

1318
    while (proc->instance_cnt_rx < 0) {
1319 1320 1321
      // 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
1322
    }
1323 1324 1325 1326 1327 1328 1329

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

1330 1331
    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 );
1332
    start_meas( &softmodem_stats_rx_sf[proc->subframe] );
1333

Raymond Knopp's avatar
 
Raymond Knopp committed
1334
    if (oai_exit) break;
1335

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

1339
      phy_procedures_eNB_RX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay );
Raymond Knopp's avatar
 
Raymond Knopp committed
1340
    }
1341 1342

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

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

    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
1358
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1359 1360

    proc->frame_rx++;
1361

Raymond Knopp's avatar
 
Raymond Knopp committed
1362 1363
    if (proc->frame_rx==1024)
      proc->frame_rx=0;
1364

1365
    stop_meas( &softmodem_stats_rx_sf[proc->subframe] );
1366 1367 1368 1369 1370 1371 1372
#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  
1373
    print_meas_now(&softmodem_stats_rx_sf[proc->subframe],"eNB_RX_SF",proc->subframe, rx_time_file);
Raymond Knopp's avatar
 
Raymond Knopp committed
1374
  }
1375

1376
  //stop_meas( &softmodem_stats_rx_sf[proc->subframe] );
1377
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 0 );
1378

Raymond Knopp's avatar
 
Raymond Knopp committed
1379
#ifdef HARD_RT
Raymond Knopp's avatar
 
Raymond Knopp committed
1380 1381 1382 1383
  rt_make_soft_real_time();
#endif

#ifdef DEBUG_THREADS
1384
  printf( "Exiting eNB thread RX %d\n", proc->subframe );
Raymond Knopp's avatar
 
Raymond Knopp committed
1385 1386 1387 1388
#endif
  // clean task
#ifdef RTAI
  rt_task_delete(task);
Raymond Knopp's avatar
 
Raymond Knopp committed
1389 1390
#endif

1391 1392
  eNB_thread_rx_status[proc->subframe] = 0;
  return &eNB_thread_rx_status[proc->subframe];
Raymond Knopp's avatar
 
Raymond Knopp committed
1393 1394 1395 1396
}



Raymond Knopp's avatar
 
Raymond Knopp committed
1397

1398 1399
void init_eNB_proc(void)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1400
  int i;
Raymond Knopp's avatar
 
Raymond Knopp committed
1401 1402
  int CC_id;

1403 1404 1405
  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
1406
     
1407

navid's avatar
navid committed
1408 1409 1410 1411 1412 1413
#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");
      
1414
      pthread_attr_init( &attr_eNB_proc_rx[CC_id][i] );
navid's avatar
navid committed
1415
      if (pthread_attr_setstacksize( &attr_eNB_proc_rx[CC_id][i], 64 * PTHREAD_STACK_MIN ) != 0)
1416
        perror("[ENB_PROC_RX] setting thread stack size failed\n");
1417
      */
1418
      // set the kernel scheduling policy and priority
Raymond Knopp's avatar
 
Raymond Knopp committed
1419 1420 1421 1422 1423 1424
      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);
1425
      printf("Setting OS scheduler to SCHED_FIFO for eNB [cc%d][thread%d] \n",CC_id, i);
1426
#endif
1427 1428 1429
      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
1430
      PHY_vars_eNB_g[0][CC_id]->proc[i].CC_id = CC_id;
1431 1432 1433 1434
      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);
1435 1436 1437 1438
#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 
1439 1440
      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] );
1441
#endif
1442 1443 1444 1445 1446
      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
1447 1448
      PHY_vars_eNB_g[0][CC_id]->proc[i].frame_tx = 0;
      PHY_vars_eNB_g[0][CC_id]->proc[i].frame_rx = 0;
1449
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
1450 1451
      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
1452
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
1453 1454
      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
1455
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1456
    }
1457 1458


1459
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
1460 1461
    // 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
1462

Raymond Knopp's avatar
 
Raymond Knopp committed
1463
    //PHY_vars_eNB_g[0][CC_id]->proc[0].frame_rx = 1023;
Raymond Knopp's avatar
 
Raymond Knopp committed
1464 1465
    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
1466
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
1467 1468
    // 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
1469
    //    PHY_vars_eNB_g[0][CC_id]->proc[7].frame_tx = 1;
Raymond Knopp's avatar
 
Raymond Knopp committed
1470 1471
    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
1472
    //    PHY_vars_eNB_g[0][CC_id]->proc[0].frame_tx = 1;
Raymond Knopp's avatar
 
Raymond Knopp committed
1473
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1474
  }
1475 1476 1477 1478 1479 1480 1481

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

1484 1485 1486 1487 1488 1489
/*!
 * \brief Terminate eNB TX and RX threads.
 */
void kill_eNB_proc(void)
{
  int *status;
Raymond Knopp's avatar
 
Raymond Knopp committed
1490

1491 1492
  for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++)
    for (int i=0; i<NUM_ENB_THREADS; i++) {
1493

Raymond Knopp's avatar
 
Raymond Knopp committed
1494
#ifdef DEBUG_THREADS
1495
      printf( "Killing TX CC_id %d thread %d\n", CC_id, i );
Raymond Knopp's avatar
 
Raymond Knopp committed
1496
#endif
1497 1498 1499

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1507
#ifdef DEBUG_THREADS
1508

1509 1510 1511 1512 1513 1514 1515 1516 1517
      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" );
        }
      }
1518

1519 1520
#else
      UNUSED(result)
Raymond Knopp's avatar
 
Raymond Knopp committed
1521
#endif
1522

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

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

1535 1536
#ifdef DEBUG_THREADS

1537 1538 1539 1540 1541 1542 1543 1544 1545
      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" );
        }
      }
1546

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

      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
1555
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1556 1557 1558
}


Raymond Knopp's avatar
 
Raymond Knopp committed
1559 1560


1561

Raymond Knopp's avatar
 
Raymond Knopp committed
1562

1563 1564 1565 1566 1567 1568
/*!
 * \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 )
1569
{
1570 1571
  UNUSED(arg);
  static int eNB_thread_status;
1572

1573
  unsigned char slot;
1574
#ifdef EXMIMO
1575
  slot=0;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1576
  RTIME time_in;
Raymond Knopp's avatar
 
Raymond Knopp committed
1577
  volatile unsigned int *DAQ_MBOX = openair0_daq_cnt();
Raymond Knopp's avatar
 
Raymond Knopp committed
1578 1579
  int mbox_target=0,mbox_current=0;
  int hw_slot,delay_cnt;
Raymond Knopp's avatar
 
Raymond Knopp committed
1580 1581
  int diff;
  int ret;
1582
  int first_run=1;
Raymond Knopp's avatar
 
Raymond Knopp committed
1583
#else
1584 1585 1586
  // the USRP implementation operates on subframes, not slots
  // one subframe consists of one even and one odd slot
  slot = 1;
1587
  int spp;
1588
  int tx_launched = 0;
1589
  int card=0;
1590 1591 1592

  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
1593

1594
  int hw_subframe = 0; // 0..NUM_ENB_THREADS-1 => 0..9
1595
  
1596
  unsigned int rx_pos = 0;
1597
  unsigned int tx_pos = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
1598
#endif
1599
  int CC_id=0;	
1600
  struct timespec trx_time0, trx_time1, trx_time2;
1601

1602
#ifdef RTAI
1603
  RT_TASK* task = rt_task_init_schmod(nam2num("eNBmain"), 0, 0, 0, SCHED_FIFO, 0xF);
1604
#else
1605
#ifdef LOWLATENCY
1606 1607 1608
  struct sched_attr attr;
  unsigned int flags = 0;

Raymond Knopp's avatar
 
Raymond Knopp committed
1609 1610 1611 1612
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1613

1614
  /* This creates a .2 ms  reservation */
Raymond Knopp's avatar
 
Raymond Knopp committed
1615
  attr.sched_policy = SCHED_DEADLINE;
navid's avatar
navid committed
1616
  attr.sched_runtime  = (0.3 * 100) * 10000;
1617 1618
  attr.sched_deadline = (0.9 * 100) * 10000;
  attr.sched_period   = 1 * 1000000;
1619

Lionel Gauthier's avatar
Lionel Gauthier committed
1620

Raymond Knopp's avatar
 
Raymond Knopp committed
1621 1622 1623 1624
  /* 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");
     }*/
1625

1626
  if (sched_setattr(0, &attr, flags) < 0 ) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1627 1628 1629 1630
    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",
1631
          gettid(),sched_getcpu());
Raymond Knopp's avatar
 
Raymond Knopp committed
1632
  }
1633

1634
#endif
1635 1636
#endif

1637 1638 1639 1640 1641
  // stop early, if an exit is requested
  // FIXME really neccessary?
  if (oai_exit)
    goto eNB_thread_cleanup;

1642
#ifdef RTAI
1643
  printf( "[SCHED][eNB] Started eNB main thread (id %p)\n", task );
Raymond Knopp's avatar
 
Raymond Knopp committed
1644
#else
1645
  printf( "[SCHED][eNB] Started eNB main thread on CPU %d TID %d\n", sched_getcpu(), gettid());
1646 1647 1648
#endif

#ifdef HARD_RT
1649
  rt_make_hard_real_time();
1650 1651
#endif

1652 1653 1654 1655 1656 1657 1658 1659
  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;
1660

1661 1662
  printf( "waiting for sync (eNB_thread)\n" );
  pthread_mutex_lock( &sync_mutex );
1663

1664 1665
  while (sync_var<0)
    pthread_cond_wait( &sync_cond, &sync_mutex );
1666

1667
  pthread_mutex_unlock(&sync_mutex);
1668

1669 1670
  printf( "got sync (eNB_thread)\n" );

1671
  int frame = 0;
1672

1673
#ifndef EXMIMO
1674 1675
  spp        = openair0_cfg[0].samples_per_packet;
  tx_pos     = openair0_cfg[0].tx_scheduling_advance;
1676
#endif
1677

1678 1679 1680 1681
#if defined(ENABLE_ITTI)
  wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB);
#endif 

1682 1683
  while (!oai_exit) {
    start_meas( &softmodem_stats_mt );
Raymond Knopp's avatar
 
Raymond Knopp committed
1684

1685
#ifdef EXMIMO
1686 1687
    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]);
1688 1689
    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);
1690 1691 1692 1693
    //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];
1694

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

1707
      if (diff<0)
1708
        diff = diff + 150;
1709

1710 1711 1712 1713
      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)))) {
1714

1715 1716 1717 1718
      // 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);
      
1719
      if (exit_missed_slots==1) {
1720 1721
        stop_meas(&softmodem_stats_mt);
        exit_fun("[HW][eNB] missed slot");
1722
      } else {
1723
        num_missed_slots++;
1724
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_MISSED_SLOTS_ENB,num_missed_slots );
1725
      }
1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747

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

    
1748
    }
1749

1750
    if (diff>8)
1751 1752
      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);
1753

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

    delay_cnt = 0;
1758

1759 1760 1761 1762
    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);
1763
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP,1);
1764
      ret = rt_sleep_ns(diff*DAQ_PERIOD);
1765 1766
      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);
1767

1768 1769
      if (ret)
        LOG_D(HW,"eNB Frame %d, time %llu: rt_sleep_ns returned %d\n",frame, time_in);
1770

Raymond Knopp's avatar
 
Raymond Knopp committed
1771
      hw_slot = (((((volatile unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15;
1772 1773 1774
      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());
1775
      delay_cnt++;
1776

1777 1778 1779 1780 1781
      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");
      }
1782

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1785
      if ((mbox_current>=135) && (mbox_target<15)) //handle the frame wrap-arround
1786
        diff = 150-mbox_current+mbox_target;
Raymond Knopp's avatar
 
Raymond Knopp committed
1787
      else if ((mbox_current<15) && (mbox_target>=135))
1788
        diff = -150+mbox_target-mbox_current;
Raymond Knopp's avatar
 
Raymond Knopp committed
1789
      else
1790 1791
        diff = mbox_target - mbox_current;
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1792

1793
#else  // EXMIMO
1794 1795
    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 );
1796
    tx_launched = 0;
1797

1798
    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
1799

1800
      unsigned int rxs;
Raymond Knopp's avatar
 
Raymond Knopp committed
1801
#ifndef USRP_DEBUG
1802 1803 1804
      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
1805

1806
      clock_gettime( CLOCK_MONOTONIC, &trx_time0 );
1807

1808
       start_meas( &softmodem_stats_hw );
1809

1810
      openair0_timestamp timestamp;
1811 1812
      int i=0;
      // prepare rx buffer pointers
1813
      for (i=0; i<PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx; i++)
1814 1815 1816 1817 1818 1819 1820
        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,
1821 1822
				     PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx);
      
1823 1824
      stop_meas( &softmodem_stats_hw );
      clock_gettime( CLOCK_MONOTONIC, &trx_time1 );
Raymond Knopp's avatar
 
Raymond Knopp committed
1825

navid's avatar
navid committed
1826
      if (frame > 20){ 
1827 1828 1829
	if (rxs != spp)
	  exit_fun( "problem receiving samples" );
      }
1830
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
1831

1832 1833 1834
      // Transmit TX buffer based on timestamp from RX


1835 1836 1837 1838 1839 1840
    
      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
1841
      if (frame > 50) {
1842
	openair0.trx_write_func(&openair0,
1843
				(timestamp+(openair0_cfg[card].tx_scheduling_advance)-openair0_cfg[card].tx_sample_advance),
1844 1845 1846 1847
				txp,
				spp,
				PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx,
				1);
navid's avatar
navid committed
1848 1849
      }
      
1850
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, timestamp&0xffffffff );
1851
      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 );
1852 1853 1854 1855

      stop_meas( &softmodem_stats_mt );
      clock_gettime( CLOCK_MONOTONIC, &trx_time2 );

1856
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE,0);
1857 1858 1859 1860 1861
#else
      // USRP_DEBUG is active
      rt_sleep_ns(1000000);
#endif

1862 1863
      if ((frame>50) &&
	  (tx_launched == 0) &&
1864 1865
          (rx_pos >= (((2*hw_subframe)+1)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))) {
        tx_launched = 1;
1866

1867
        for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895
          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;

1896 1897
      if (tx_pos >= openair0_cfg[card].samples_per_frame)
        tx_pos -= openair0_cfg[card].samples_per_frame;
1898 1899
    }

1900 1901
    if (rx_pos >= openair0_cfg[card].samples_per_frame)
      rx_pos -= openair0_cfg[card].samples_per_frame;
1902

Raymond Knopp's avatar
 
Raymond Knopp committed
1903 1904

#endif // USRP
1905

1906
    if (oai_exit) break;
Raymond Knopp's avatar
 
Raymond Knopp committed
1907

1908 1909 1910 1911 1912
    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;
1913

1914 1915
      if (time_diff < timing_info.time_min)
        timing_info.time_min = time_diff;
1916

1917 1918
      if (time_diff > timing_info.time_max)
        timing_info.time_max = time_diff;
1919

1920 1921 1922 1923 1924 1925
      timing_info.time_avg += time_diff;
    }

    timing_info.n_samples++;

    if ((slot&1) == 1) {
1926
      // odd slot
1927
#ifdef EXMIMO
1928
      int sf = ((slot>>1)+1)%10;
Raymond Knopp's avatar
 
Raymond Knopp committed
1929
#else
1930
      int sf = hw_subframe;
Raymond Knopp's avatar
 
Raymond Knopp committed
1931
#endif
1932 1933
      if (frame>50) {
	for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1934
#ifdef EXMIMO
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[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);
1950
	      exit_fun("nothing to add");
1951 1952 1953
	    }
	  }
	  
Raymond Knopp's avatar
 
Raymond Knopp committed
1954 1955
#endif

1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978
	  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
1979
      }
1980 1981 1982 1983
    }

#ifdef EXMIMO
    slot++;
1984

1985 1986 1987 1988
    if (slot == 20) {
      frame++;
      slot = 0;
    }
1989

Raymond Knopp's avatar
 
Raymond Knopp committed
1990
#else
1991 1992
    hw_subframe++;
    slot += 2;
1993

1994
    if (hw_subframe == NUM_ENB_THREADS) {
1995
      // the radio frame is complete, start over
1996 1997 1998 1999
      hw_subframe = 0;
      frame++;
      slot = 1;
    }
2000 2001

#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2002

2003
#if defined(ENABLE_ITTI)
2004
    itti_update_lte_time( frame, slot );
2005
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2006
  }
2007 2008

eNB_thread_cleanup:
Raymond Knopp's avatar
 
Raymond Knopp committed
2009
#ifdef DEBUG_THREADS
2010
  printf( "eNB_thread: finished, ran %d times.\n", frame );
Raymond Knopp's avatar
 
Raymond Knopp committed
2011
#endif
2012

2013
#ifdef HARD_RT
Raymond Knopp's avatar
 
Raymond Knopp committed
2014
  rt_make_soft_real_time();
2015 2016
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
2017
#ifdef DEBUG_THREADS
2018
  printf( "Exiting eNB_thread ..." );
Raymond Knopp's avatar
 
Raymond Knopp committed
2019 2020
#endif
  // clean task
2021
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
2022
  rt_task_delete(task);
2023
#endif
2024 2025 2026

  eNB_thread_status = 0;
  return &eNB_thread_status;
Raymond Knopp's avatar
 
Raymond Knopp committed
2027
}
2028

2029

Raymond Knopp's avatar
 
Raymond Knopp committed
2030

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2031

2032 2033
static void get_options (int argc, char **argv)
{
2034 2035 2036
  int c;
  //  char                          line[1000];
  //  int                           l;
2037
  int k,i;//,j,k;
2038
#if defined(OAI_USRP) || defined(CPRIGW)
2039
  int clock_src;
2040
#endif
2041 2042 2043 2044 2045
  int CC_id;
#ifdef EXMIMO
  char rxg_fname[256], line[1000];
  FILE *rxg_fd;
  int l;
2046
#endif
2047 2048 2049



2050 2051

  const Enb_properties_array_t *enb_properties;
2052

2053 2054 2055 2056 2057 2058 2059
  enum long_option_e {
    LONG_OPTION_START = 0x100, /* Start after regular single char options */
    LONG_OPTION_ULSCH_MAX_CONSECUTIVE_ERRORS,
    LONG_OPTION_CALIB_UE_RX,
    LONG_OPTION_CALIB_UE_RX_MED,
    LONG_OPTION_CALIB_UE_RX_BYP,
    LONG_OPTION_DEBUG_UE_PRACH,
2060
    LONG_OPTION_NO_L2_CONNECT,
Raymond Knopp's avatar
 
Raymond Knopp committed
2061
    LONG_OPTION_CALIB_PRACH_TX,
2062 2063
    LONG_OPTION_RXGAIN,
    LONG_OPTION_TXGAIN,
2064
    LONG_OPTION_SCANCARRIER,
2065 2066
    LONG_OPTION_MAXPOWER,
    LONG_OPTION_DUMP_FRAME,
2067 2068
    LONG_OPTION_LOOPMEMORY,
    LONG_OPTION_PHYTEST
2069
  };
2070

2071 2072 2073 2074 2075 2076 2077
  static const struct option long_options[] = {
    {"ulsch-max-errors",required_argument,  NULL, LONG_OPTION_ULSCH_MAX_CONSECUTIVE_ERRORS},
    {"calib-ue-rx",     required_argument,  NULL, LONG_OPTION_CALIB_UE_RX},
    {"calib-ue-rx-med", required_argument,  NULL, LONG_OPTION_CALIB_UE_RX_MED},
    {"calib-ue-rx-byp", required_argument,  NULL, LONG_OPTION_CALIB_UE_RX_BYP},
    {"debug-ue-prach",  no_argument,        NULL, LONG_OPTION_DEBUG_UE_PRACH},
    {"no-L2-connect",   no_argument,        NULL, LONG_OPTION_NO_L2_CONNECT},
Raymond Knopp's avatar
 
Raymond Knopp committed
2078 2079 2080 2081
    {"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},
2082
    {"ue-max-power",   required_argument,  NULL, LONG_OPTION_MAXPOWER},
2083 2084
    {"ue-dump-frame", no_argument, NULL, LONG_OPTION_DUMP_FRAME},
    {"loop-memory", required_argument, NULL, LONG_OPTION_LOOPMEMORY},
2085
    {"phy-test", no_argument, NULL, LONG_OPTION_PHYTEST},
2086 2087 2088
    {NULL, 0, NULL, 0}
  };

2089
  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) {
2090
    switch (c) {
2091 2092 2093 2094 2095
    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];

2096 2097 2098 2099
    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;
2100

2101 2102 2103 2104 2105
    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;
2106

2107 2108 2109 2110
    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
2111
      break;
2112

2113 2114 2115 2116 2117
    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;
2118

2119 2120 2121
    case LONG_OPTION_DEBUG_UE_PRACH:
      mode = debug_prach;
      break;
2122

2123 2124 2125
    case LONG_OPTION_NO_L2_CONNECT:
      mode = no_L2_connect;
      break;
2126

Raymond Knopp's avatar
 
Raymond Knopp committed
2127 2128 2129 2130
    case LONG_OPTION_CALIB_PRACH_TX:
      mode = calib_prach_tx;
      break;

2131
    case LONG_OPTION_RXGAIN:
2132 2133
      for (i=0; i<4; i++)
        rx_gain[0][i] = atof(optarg);
2134

2135
      break;
2136

2137 2138 2139
    case LONG_OPTION_TXGAIN:
      for (i=0; i<4; i++)
        tx_gain[0][i] = atof(optarg);
2140

2141
      break;
2142

2143 2144 2145 2146 2147
    case LONG_OPTION_SCANCARRIER:
      UE_scan_carrier=1;

      break;

2148 2149 2150 2151 2152 2153 2154 2155 2156 2157
    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;
     break;

2158 2159 2160 2161
    case LONG_OPTION_PHYTEST:
      phy_test = 1;
      break;

2162 2163 2164
    case 'M':
#ifdef ETHERNET
      strcpy(rrh_eNB_ip,optarg);
2165
#endif
2166
      break;
2167

2168 2169 2170 2171
    case 'A':
      timing_advance = atoi (optarg);
      break;

2172
    case 'C':
2173 2174 2175 2176 2177 2178
      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]);
2179
      }
2180

2181
      UE_scan=0;
2182

2183
      break;
2184

Florian Kaltenberger's avatar
Florian Kaltenberger committed
2185 2186 2187 2188
    case 'a':
      chain_offset = atoi(optarg);
      break;

2189 2190 2191 2192
    case 'd':
#ifdef XFORMS
      do_forms=1;
      printf("Running with XFORMS!\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2193
#endif
2194
      break;
2195 2196 2197 2198
      
    case 'E':
      threequarter_fs=1;
      break;
2199

2200 2201 2202
    case 'K':
#if defined(ENABLE_ITTI)
      itti_dump_file = strdup(optarg);
2203
#else
2204
      printf("-K option is disabled when ENABLE_ITTI is not defined\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2205
#endif
2206
      break;
2207

2208 2209 2210
    case 'O':
      conf_config_file_name = optarg;
      break;
2211

2212 2213 2214
    case 'U':
      UE_flag = 1;
      break;
2215

2216 2217 2218
    case 'm':
      target_dl_mcs = atoi (optarg);
      break;
2219

2220 2221 2222
    case 't':
      target_ul_mcs = atoi (optarg);
      break;
2223

2224 2225 2226 2227 2228 2229 2230
    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");
      /*
2231 2232 2233
      if (optarg == NULL){
      in_ip[0] =NULL;
      printf("Enabling OPT for wireshark for local interface");
2234
      } else {
2235 2236 2237
      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);
2238 2239 2240
      }
      */
      break;
2241

2242
    case 'P':
2243 2244
      opt_type = OPT_PCAP;
      opt_enabled=1;
2245 2246 2247 2248 2249

      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");
2250
      } else {
2251 2252 2253
        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);
2254
      }
2255 2256 2257

      break;

Raymond Knopp's avatar
 
Raymond Knopp committed
2258 2259 2260
    case 'V':
      ouput_vcd = 1;
      break;
2261

Raymond Knopp's avatar
 
Raymond Knopp committed
2262
    case  'q':
Raymond Knopp's avatar
 
Raymond Knopp committed
2263 2264
      opp_enabled = 1;
      break;
2265

Raymond Knopp's avatar
 
Raymond Knopp committed
2266 2267 2268
    case  'R' :
      online_log_messages =1;
      break;
2269

Raymond Knopp's avatar
 
Raymond Knopp committed
2270
    case 'r':
2271
      UE_scan = 0;
2272

2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298
      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
2299
      }
2300

2301
      break;
2302

Raymond Knopp's avatar
 
Raymond Knopp committed
2303
    case 's':
2304
#if defined(OAI_USRP) || defined(CPRIGW)
Raymond Knopp's avatar
 
Raymond Knopp committed
2305 2306

      clock_src = atoi(optarg);
2307

Raymond Knopp's avatar
 
Raymond Knopp committed
2308
      if (clock_src == 0) {
2309 2310 2311 2312 2313
        //  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
2314
      }
2315

Raymond Knopp's avatar
 
Raymond Knopp committed
2316 2317 2318 2319
#else
      printf("Note: -s not defined for ExpressMIMO2\n");
#endif
      break;
2320

2321 2322 2323 2324
    case 'S':
      exit_missed_slots=0;
      printf("Skip exit for missed slots\n");
      break;
2325

2326
    case 'g':
Raymond Knopp's avatar
 
Raymond Knopp committed
2327
      glog_level=atoi(optarg); // value between 1 - 9
2328
      break;
2329 2330

    case 'F':
2331
#ifdef EXMIMO
2332 2333
      sprintf(rxg_fname,"%srxg.lime",optarg);
      rxg_fd = fopen(rxg_fname,"r");
2334

2335
      if (rxg_fd) {
2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353
        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);

2354
#endif
2355
      break;
2356

2357 2358 2359
    case 'G':
      glog_verbosity=atoi(optarg);// value from 0, 0x5, 0x15, 0x35, 0x75
      break;
2360

2361 2362
    case 'x':
      transmission_mode = atoi(optarg);
2363

2364
      if (transmission_mode > 2) {
2365 2366
        printf("Transmission mode > 2 (%d) not supported for the moment\n",transmission_mode);
        exit(-1);
2367
      }
2368
      break;
2369

2370 2371 2372
    case 'T':
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) 
	frame_parms[CC_id]->frame_type = TDD;
2373
      break;
2374

2375 2376 2377 2378
    case 'h':
      help ();
      exit (-1);
       
Raymond Knopp's avatar
 
Raymond Knopp committed
2379
    default:
2380 2381
      help ();
      exit (-1);
Raymond Knopp's avatar
 
Raymond Knopp committed
2382
      break;
2383 2384
    }
  }
2385

Raymond Knopp's avatar
 
Raymond Knopp committed
2386 2387
  if (UE_flag == 0)
    AssertFatal(conf_config_file_name != NULL,"Please provide a configuration file\n");
2388 2389


Raymond Knopp's avatar
 
Raymond Knopp committed
2390
  if ((UE_flag == 0) && (conf_config_file_name != NULL)) {
2391
    int i,j;
2392

Raymond Knopp's avatar
 
Raymond Knopp committed
2393
    NB_eNB_INST = 1;
2394

Raymond Knopp's avatar
 
Raymond Knopp committed
2395 2396
    /* Read eNB configuration file */
    enb_properties = enb_config_init(conf_config_file_name);
2397

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

Raymond Knopp's avatar
 
Raymond Knopp committed
2402
    /* Update some simulation parameters */
2403
    for (i=0; i < enb_properties->number; i++) {
2404
      AssertFatal (MAX_NUM_CCs == enb_properties->properties[i]->nb_cc,
2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421
                   "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);

      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
2422 2423
      }

2424

2425 2426 2427
      init_all_otg(0);
      g_otg->seed = 0;
      init_seeds(g_otg->seed);
2428 2429 2430 2431 2432 2433 2434 2435 2436 2437

      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");
2438
      }
2439

2440
      init_predef_traffic(enb_properties->properties[i]->num_otg_elements, 1);
2441 2442


2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456
      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
2457 2458 2459 2460 2461 2462
# 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
2463 2464 2465
#if defined (ENABLE_SECURITY)
      osa_log_level                  = enb_properties->properties[i]->osa_log_level;
      osa_log_verbosity              = enb_properties->properties[i]->osa_log_verbosity;
2466
#endif
Florian Kaltenberger's avatar
Florian Kaltenberger committed
2467

Raymond Knopp's avatar
 
Raymond Knopp committed
2468
      // adjust the log
2469
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
2470 2471 2472 2473 2474 2475 2476 2477 2478 2479
        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
2480
      } // CC_id
2481
    }// i
2482 2483 2484 2485 2486 2487 2488 2489
  } 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
2490
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
2491
}
2492

2493 2494
int main( int argc, char **argv )
{
2495
  int i,aa,card=0;
Lionel Gauthier's avatar
Lionel Gauthier committed
2496
#if defined (XFORMS) || defined (EMOS) || defined (EXMIMO)
Raymond Knopp's avatar
 
Raymond Knopp committed
2497
  void *status;
2498
#endif
2499

Raymond Knopp's avatar
 
Raymond Knopp committed
2500
  int CC_id;
Raymond Knopp's avatar
 
Raymond Knopp committed
2501
  uint16_t Nid_cell = 0;
2502
  uint8_t  cooperation_flag=0,  abstraction_flag=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2503
  uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2;
2504 2505

#ifdef ENABLE_TCXO
Raymond Knopp's avatar
 
Raymond Knopp committed
2506
  unsigned int tcxo = 114;
2507 2508
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
2509
#if defined (XFORMS)
2510 2511
  int ret;
#endif
2512
#if defined (EMOS) || (! defined (RTAI))
Raymond Knopp's avatar
 
Raymond Knopp committed
2513
  int error_code;
2514
#endif
2515

2516 2517 2518 2519 2520
#ifdef DEBUG_CONSOLE
  setvbuf(stdout, NULL, _IONBF, 0);
  setvbuf(stderr, NULL, _IONBF, 0);
#endif

2521 2522 2523
  PHY_VARS_UE *UE[MAX_NUM_CCs];

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

2526
  memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
Raymond Knopp's avatar
 
Raymond Knopp committed
2527
  set_latency_target();
2528

2529
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2530 2531
    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 */
2532
    frame_parms[CC_id]->frame_type          = FDD;
Raymond Knopp's avatar
 
Raymond Knopp committed
2533 2534
    frame_parms[CC_id]->tdd_config          = 3;
    frame_parms[CC_id]->tdd_config_S        = 0;
2535 2536
    frame_parms[CC_id]->N_RB_DL             = 100;
    frame_parms[CC_id]->N_RB_UL             = 100;
Raymond Knopp's avatar
 
Raymond Knopp committed
2537
    frame_parms[CC_id]->Ncp                 = NORMAL;
Raymond Knopp's avatar
 
Raymond Knopp committed
2538 2539
    frame_parms[CC_id]->Ncp_UL              = NORMAL;
    frame_parms[CC_id]->Nid_cell            = Nid_cell;
Raymond Knopp's avatar
 
Raymond Knopp committed
2540
    frame_parms[CC_id]->num_MBSFN_config    = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2541 2542 2543
    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
2544
  }
2545

2546 2547 2548 2549 2550
  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];
2551
    //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
2552
  }
2553 2554
  logInit();
 
2555
  get_options (argc, argv); //Command-line options
2556 2557 2558
 
  
  // initialize the log (see log.h for details)
Florian Kaltenberger's avatar
Florian Kaltenberger committed
2559 2560
  set_glog(glog_level, glog_verbosity);

2561 2562
  //randominit (0);
  set_taus_seed (0);
Raymond Knopp's avatar
 
Raymond Knopp committed
2563

2564 2565
  if (UE_flag==1) {
    printf("configuring for UE\n");
2566

2567 2568
    set_comp_log(HW,      LOG_DEBUG,  LOG_HIGH, 1);
    set_comp_log(PHY,     LOG_DEBUG,   LOG_HIGH, 1);
2569 2570 2571 2572 2573
    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);
2574
#if defined(ENABLE_ITTI)
2575
    set_comp_log(EMU,     LOG_INFO,   LOG_MED, 1);
2576
# if defined(ENABLE_USE_MME)
2577
    set_comp_log(NAS,     LOG_INFO,   LOG_HIGH, 1);
2578 2579
# endif
#endif
2580 2581
  } else {
    printf("configuring for eNB\n");
2582

2583 2584 2585 2586 2587 2588 2589 2590
    set_comp_log(HW,      hw_log_level, hw_log_verbosity, 1);
    set_comp_log(PHY,     phy_log_level,   phy_log_verbosity, 1);
    if (opt_enabled == 1 )
      set_comp_log(OPT,   opt_log_level,      opt_log_verbosity, 1);
    set_comp_log(MAC,     mac_log_level,  mac_log_verbosity, 1);
    set_comp_log(RLC,     rlc_log_level,   rlc_log_verbosity, 1);
    set_comp_log(PDCP,    pdcp_log_level,  pdcp_log_verbosity, 1);
    set_comp_log(RRC,     rrc_log_level,  rrc_log_verbosity, 1);
2591
#if defined(ENABLE_ITTI)
2592
    set_comp_log(EMU,     LOG_INFO,   LOG_MED, 1);
2593
# if defined(ENABLE_USE_MME)
2594 2595 2596 2597
    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);
2598
# endif
2599
#if defined(ENABLE_SECURITY)
2600
    set_comp_log(OSA,    osa_log_level,   osa_log_verbosity, 1);
2601
#endif
2602
#endif
2603
#ifdef LOCALIZATION
2604 2605 2606 2607 2608 2609 2610 2611 2612
    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
2613
    }
2614
  }
2615

Raymond Knopp's avatar
 
Raymond Knopp committed
2616 2617
  if (ouput_vcd) {
    if (UE_flag==1)
2618
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_UE.vcd");
Raymond Knopp's avatar
 
Raymond Knopp committed
2619
    else
2620
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_eNB.vcd");
Raymond Knopp's avatar
 
Raymond Knopp committed
2621
  }
2622

2623
  if (opp_enabled ==1){
2624
    reset_opp_meas();
2625 2626
  }
  cpuf=get_cpu_freq_GHz();
2627

2628
#if defined(ENABLE_ITTI)
2629

Raymond Knopp's avatar
 
Raymond Knopp committed
2630 2631
  if (UE_flag == 1) {
    log_set_instance_type (LOG_INSTANCE_UE);
2632
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
2633 2634
    log_set_instance_type (LOG_INSTANCE_ENB);
  }
2635

Raymond Knopp's avatar
 
Raymond Knopp committed
2636
  itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, itti_dump_file);
2637
 
2638 2639
  // initialize mscgen log after ITTI
  MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX);
2640 2641
#endif
 
2642 2643
  if (opt_type != OPT_NONE) {
    radio_type_t radio_type;
2644

2645 2646
    if (frame_parms[0]->frame_type == FDD)
      radio_type = RADIO_TYPE_FDD;
2647
    else
2648
      radio_type = RADIO_TYPE_TDD;
2649

2650 2651 2652
    if (init_opt(in_path, in_ip, NULL, radio_type) == -1)
      LOG_E(OPT,"failed to run OPT \n");
  }
2653

2654
#ifdef PDCP_USE_NETLINK
Raymond Knopp's avatar
 
Raymond Knopp committed
2655
  netlink_init();
2656 2657 2658
#if defined(PDCP_USE_NETLINK_QUEUES)
  pdcp_netlink_init();
#endif
2659 2660
#endif

2661
#if !defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
2662 2663 2664
  // to make a graceful exit when ctrl-c is pressed
  signal(SIGSEGV, signal_handler);
  signal(SIGINT, signal_handler);
2665
#endif
2666 2667

#ifndef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
2668 2669 2670 2671
  check_clock();
#endif

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

2675 2676 2677 2678 2679 2680 2681 2682 2683
    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
2684 2685 2686 2687 2688 2689 2690 2691
    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;
2692
    frame_parms[CC_id]->threequarter_fs = threequarter_fs;
2693 2694
    init_ul_hopping(frame_parms[CC_id]);
    init_frame_parms(frame_parms[CC_id],1);
2695 2696
    //   phy_init_top(frame_parms[CC_id]);
    phy_init_lte_top(frame_parms[CC_id]);
Raymond Knopp's avatar
 
Raymond Knopp committed
2697 2698 2699
  }


2700
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2701
    //init prach for openair1 test
2702
    frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22;
Raymond Knopp's avatar
 
Raymond Knopp committed
2703
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1;
2704
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2705 2706 2707
    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
2708
    // N_ZC = (prach_fmt <4)?839:139;
Raymond Knopp's avatar
 
Raymond Knopp committed
2709
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
2710 2711

  if (UE_flag==1) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2712 2713 2714
    NB_UE_INST=1;
    NB_INST=1;

Raymond Knopp's avatar
 
Raymond Knopp committed
2715 2716
    PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE**));
    PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_UE*)*MAX_NUM_CCs);
2717 2718

    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
2719 2720 2721 2722

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

2724 2725 2726 2727
      if (phy_test==1)
	UE[CC_id]->mac_enabled = 0;
      else 
	UE[CC_id]->mac_enabled = 1;
2728

2729 2730 2731 2732 2733 2734 2735 2736 2737 2738
      if (UE[CC_id]->mac_enabled == 0) {
	for (i=0; i<NUMBER_OF_CONNECTED_eNB_MAX; i++) {
	  UE[CC_id]->pusch_config_dedicated[i].betaOffset_ACK_Index = beta_ACK;
	  UE[CC_id]->pusch_config_dedicated[i].betaOffset_RI_Index  = beta_RI;
	  UE[CC_id]->pusch_config_dedicated[i].betaOffset_CQI_Index = beta_CQI;
	  
	  UE[CC_id]->scheduling_request_config[i].sr_PUCCH_ResourceIndex = 0;
	  UE[CC_id]->scheduling_request_config[i].sr_ConfigIndex = 7+(0%3);
	  UE[CC_id]->scheduling_request_config[i].dsr_TransMax = sr_n4;
	}
Raymond Knopp's avatar
 
Raymond Knopp committed
2739
      }
2740

2741
      UE[CC_id]->UE_scan = UE_scan;
2742
      UE[CC_id]->UE_scan_carrier = UE_scan_carrier;
2743 2744 2745
      UE[CC_id]->mode    = mode;

      compute_prach_seq(&UE[CC_id]->lte_frame_parms.prach_config_common,
2746 2747 2748
                        UE[CC_id]->lte_frame_parms.frame_type,
                        UE[CC_id]->X_u);

2749 2750 2751 2752
      if (UE[CC_id]->mac_enabled == 1) 
	UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1234;
      else
	UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1235;
2753

2754
#ifdef EXMIMO
2755 2756 2757 2758
      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
2759
      }
2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778

      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
2779
      }
2780

2781
#else
2782
      UE[CC_id]->rx_total_gain_dB =  (int)rx_gain[CC_id][0];
2783
#endif
2784

2785
      UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id];
2786

2787

2788
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
2789
      //N_TA_offset
2790
      if (UE[CC_id]->lte_frame_parms.frame_type == TDD) {
2791 2792 2793 2794 2795 2796 2797 2798
        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
2799
      }
2800
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
2801
      //already taken care of in lte-softmodem
2802
      UE[CC_id]->N_TA_offset = 0;
2803
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2804
    }
2805

Raymond Knopp's avatar
 
Raymond Knopp committed
2806 2807 2808 2809
    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;
2810 2811 2812



Raymond Knopp's avatar
 
Raymond Knopp committed
2813
    //  printf("tx_max_power = %d -> amp %d\n",tx_max_power,get_tx_amp(tx_max_power,tx_max_power));
2814 2815 2816 2817 2818 2819
  } 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++) {
2820
      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);
2821 2822
      PHY_vars_eNB_g[0][CC_id]->CC_id = CC_id;

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

2828 2829 2830 2831 2832 2833 2834 2835 2836 2837
      if (PHY_vars_eNB_g[0][CC_id]->mac_enabled == 0) {
	for (i=0; i<NUMBER_OF_UE_MAX; i++) {
	  PHY_vars_eNB_g[0][CC_id]->pusch_config_dedicated[i].betaOffset_ACK_Index = beta_ACK;
	  PHY_vars_eNB_g[0][CC_id]->pusch_config_dedicated[i].betaOffset_RI_Index  = beta_RI;
	  PHY_vars_eNB_g[0][CC_id]->pusch_config_dedicated[i].betaOffset_CQI_Index = beta_CQI;
	  
	  PHY_vars_eNB_g[0][CC_id]->scheduling_request_config[i].sr_PUCCH_ResourceIndex = i;
	  PHY_vars_eNB_g[0][CC_id]->scheduling_request_config[i].sr_ConfigIndex = 7+(i%3);
	  PHY_vars_eNB_g[0][CC_id]->scheduling_request_config[i].dsr_TransMax = sr_n4;
	}
2838 2839 2840 2841 2842
      }

      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
2843

2844
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
2845

2846
      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
2847

2848
#else
2849 2850 2851
      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
2852

2853 2854 2855
      // 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
2856

2857
#endif
2858

2859
#ifdef EXMIMO
2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870

      //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
2871
      }
2872

2873
#else
2874
      //already taken care of in lte-softmodem.c
2875 2876
      PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 0;
#endif
2877

2878
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
2879 2880


2881 2882 2883 2884 2885 2886 2887 2888 2889
    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;

  }
2890 2891 2892 2893
#ifndef RTAI
  fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx);
  cpuf=get_cpu_freq_GHz();
#endif 
2894

Raymond Knopp's avatar
 
Raymond Knopp committed
2895
  dump_frame_parms(frame_parms[0]);
2896

2897 2898 2899
  for (card=0; card<MAX_CARDS; card++) {

    if(frame_parms[0]->N_RB_DL == 100) {
2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911
      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;
      }
2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927
    } 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;
    }
2928 2929 2930 2931 2932 2933

    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
2934
#ifdef ETHERNET
2935

2936
    //calib needed
2937 2938
    openair0_cfg[card].tx_scheduling_advance = 0;
    openair0_cfg[card].tx_sample_advance = 0;
2939 2940 2941 2942 2943
    
    if (frame_parms[0]->N_RB_DL == 6) 
      openair0_cfg[card].samples_per_packet = 256;
    else 
      openair0_cfg[card].samples_per_packet = 1024;
Raymond Knopp's avatar
 
Raymond Knopp committed
2944

2945
    printf("HW: samples_per_packet %d\n",openair0_cfg[card].samples_per_packet);
Raymond Knopp's avatar
 
Raymond Knopp committed
2946 2947
#endif

2948

2949
    printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card,
2950 2951
           ((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
2952 2953
    openair0_cfg[card].Mod_id = 0;
#ifdef ETHERNET
2954 2955

    if (UE_flag) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2956
      printf("ETHERNET: Configuring UE ETH for %s:%d\n",rrh_UE_ip,rrh_UE_port);
2957 2958
      openair0_cfg[card].remote_ip   = &rrh_UE_ip[0];
      openair0_cfg[card].remote_port = rrh_UE_port;
2959 2960
    } else {
      printf("ETHERNET: Configuring eNB ETH for %s:%d\n",rrh_eNB_ip,rrh_eNB_port);
2961 2962
      openair0_cfg[card].remote_ip   = &rrh_eNB_ip[0];
      openair0_cfg[card].remote_port = rrh_eNB_port;
ghaddab's avatar
ghaddab committed
2963
    }
2964
    openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL;
Raymond Knopp's avatar
 
Raymond Knopp committed
2965
#endif
2966

2967
    // in the case of the USRP, the following variables need to be initialized before the init
2968
    // since the USRP only supports one CC (for the moment), we initialize all the cards with first CC.
2969
    // in the case of EXMIMO2, these values are overwirtten in the function setup_eNB/UE_buffer
2970
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
2971 2972
    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));
2973 2974

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

2976 2977 2978 2979 2980 2981 2982 2983
      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]);
      
2984
      openair0_cfg[card].autocal[i] = 1;
2985
      openair0_cfg[card].tx_gain[i] = tx_gain[0][i];
2986 2987 2988 2989
      if (UE_flag == 0) {
	openair0_cfg[card].rx_gain[i] = PHY_vars_eNB_g[0][0]->rx_total_gain_eNB_dB;
      }
      else {
2990
	openair0_cfg[card].rx_gain[i] = PHY_vars_UE_g[0][0]->rx_total_gain_dB;
2991
      }
2992

2993
#if 0  // UHD 3.8     
2994 2995
      switch(frame_parms[0]->N_RB_DL) {
      case 6:
2996
        openair0_cfg[card].rx_gain[i] -= 12;
2997 2998
        break;

2999
      case 25:
3000
        openair0_cfg[card].rx_gain[i] -= 6;
3001 3002
        break;

3003
      case 50:
3004 3005 3006 3007 3008
        openair0_cfg[card].rx_gain[i] -= 3;
        break;

      case 100:
        openair0_cfg[card].rx_gain[i] -= 0;
3009 3010
        break;

3011
      default:
3012
        break;
3013
      }
3014
#endif      
3015

Raymond Knopp's avatar
 
Raymond Knopp committed
3016
    }
3017

3018
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3019
  }
3020

navid's avatar
navid committed
3021 3022
  openair0.func_type = BBU_FUNC;
  openair0_cfg[0].log_level = glog_level;
3023

3024 3025 3026 3027 3028 3029 3030 3031
  if (mode!=loop_through_memory){
    int ret;
    ret= openair0_device_init(&openair0, &openair0_cfg[0]);
    printf("openair0_device_init returns %d\n",ret);
    if (ret<0) {
      printf("Exiting, cannot initialize device\n");
      exit(-1);
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3032
  }
3033
  else if (mode==loop_through_memory) {    
3034
  }
3035
 
3036
  printf("Done\n");
3037 3038 3039

  mac_xface = malloc(sizeof(MAC_xface));

Raymond Knopp's avatar
 
Raymond Knopp committed
3040
  int eMBMS_active=0;
3041
  
Raymond Knopp's avatar
 
Raymond Knopp committed
3042
  l2_init(frame_parms[0],eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL,
3043 3044 3045
	  0,// cba_group_active
	  0); // HO flag
  
Raymond Knopp's avatar
 
Raymond Knopp committed
3046
  mac_xface->macphy_exit = &exit_fun;
3047

winckel's avatar
winckel committed
3048
#if defined(ENABLE_ITTI)
3049

Raymond Knopp's avatar
 
Raymond Knopp committed
3050
  if (create_tasks(UE_flag ? 0 : 1, UE_flag ? 1 : 0) < 0) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3051
    printf("cannot create ITTI tasks\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3052 3053
    exit(-1); // need a softer mode
  }
3054

Raymond Knopp's avatar
 
Raymond Knopp committed
3055
  printf("ITTI tasks created\n");
winckel's avatar
winckel committed
3056
#endif
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3057

3058 3059 3060 3061 3062 3063 3064 3065
  if (phy_test==0) {
    if (UE_flag==1) {
      printf("Filling UE band info\n");
      fill_ue_band_info();
      mac_xface->dl_phy_sync_success (0, 0, 0, 1);
    } else
      mac_xface->mrbch_phy_sync_failure (0, 0, 0);
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
3066

3067
  /* #ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
3068 3069 3070 3071 3072 3073
  //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
3074 3075 3076 3077 3078 3079
  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
3080 3081 3082
  }
  init_predef_traffic(UE_flag ? 1 : 0, UE_flag ? 0 : 1);
  //  }
3083
  #endif */
Raymond Knopp's avatar
 
Raymond Knopp committed
3084

3085
#ifdef EXMIMO
3086
  number_of_cards = openair0_num_detected_cards;
3087 3088
#else
  number_of_cards = 1;
3089
#endif
3090

3091

3092

3093
  for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3094
    rf_map[CC_id].card=0;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3095
    rf_map[CC_id].chain=CC_id+chain_offset;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3096
  }
3097

Raymond Knopp's avatar
 
Raymond Knopp committed
3098 3099
  // connect the TX/RX buffers
  if (UE_flag==1) {
3100
#ifdef OAI_USRP
3101
    openair_daq_vars.timing_advance = timing_advance;
3102
#else
3103
    openair_daq_vars.timing_advance = 160;
3104
#endif
3105
    if (setup_ue_buffers(UE,&openair0_cfg[0],rf_map)!=0) {
3106 3107 3108
      printf("Error setting up eNB buffer\n");
      exit(-1);
    }
3109

3110
    printf("Setting UE buffer to all-RX\n");
3111

3112
    // Set LSBs for antenna switch (ExpressMIMO)
3113
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3114
      for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++)
3115 3116
        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
3117
    }
3118

3119 3120 3121 3122 3123 3124 3125
    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
3126
    //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX;
3127
  } else {
3128
    openair_daq_vars.timing_advance = 0;
3129

3130 3131 3132 3133
    if (setup_eNB_buffers(PHY_vars_eNB_g[0],&openair0_cfg[0],rf_map)!=0) {
      printf("Error setting up eNB buffer\n");
      exit(-1);
    }
3134

3135
    printf("Setting eNB buffer to all-RX\n");
3136

3137
    // Set LSBs for antenna switch (ExpressMIMO)
3138
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3139
      for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++)
3140 3141
        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
3142
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3143
  }
3144

3145
#ifdef EXMIMO
3146
  openair0_config(&openair0_cfg[0],UE_flag);
Raymond Knopp's avatar
 
Raymond Knopp committed
3147 3148
#endif

3149
  /*
Raymond Knopp's avatar
 
Raymond Knopp committed
3150 3151
      for (ant=0;ant<4;ant++)
      p_exmimo_config->rf.do_autocal[ant] = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3152
  */
3153 3154

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3157 3158 3159 3160 3161 3162
  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);
3163
  else
Raymond Knopp's avatar
 
Raymond Knopp committed
3164
    printf("[OPENAIR][SCHED][INIT] Problem creating EMOS FIFO %d, error_code %d\n",CHANSOUNDER_FIFO_MINOR,error_code);
3165

3166 3167
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3168
  mlockall(MCL_CURRENT | MCL_FUTURE);
3169 3170

#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3171
  // make main thread LXRT soft realtime
3172
  /* task = */ rt_task_init_schmod(nam2num("MAIN"), 9, 0, 0, SCHED_FIFO, 0xF);
Raymond Knopp's avatar
 
Raymond Knopp committed
3173 3174 3175 3176 3177

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3180 3181
  pthread_cond_init(&sync_cond,NULL);
  pthread_mutex_init(&sync_mutex, NULL);
3182

3183
  /*  this is moved to the eNB main thread */ 
3184

3185
//#if defined(ENABLE_ITTI)
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3186
  // Wait for eNB application initialization to be complete (eNB registration to MME)
3187 3188 3189 3190 3191
  //  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
3192

Raymond Knopp's avatar
 
Raymond Knopp committed
3193 3194

  // this starts the DMA transfers
3195
#ifdef EXMIMO
3196

Raymond Knopp's avatar
 
Raymond Knopp committed
3197
  if (UE_flag!=1)
3198
    for (card=0; card<openair0_num_detected_cards; card++)
3199
      openair0_start_rt_acquisition(card);
3200

Raymond Knopp's avatar
 
Raymond Knopp committed
3201
#endif
3202 3203

#ifdef XFORMS
3204 3205
  int UE_id;

Raymond Knopp's avatar
 
Raymond Knopp committed
3206 3207
  if (do_forms==1) {
    fl_initialize (&argc, argv, NULL, 0, 0);
3208 3209

    if (UE_flag==0) {
3210
      form_stats_l2 = create_form_stats_form();
3211 3212 3213
      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");
3214 3215

      for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228
	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");
	  }
	}
3229
      }
3230
    } else {
3231 3232 3233 3234 3235 3236 3237
      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
3238
      if (openair_daq_vars.use_ia_receiver) {
3239 3240 3241 3242 3243
        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
3244 3245 3246
      }
    }

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

3249 3250
    if (ret == 0)
      pthread_setname_np( forms_thread, "xforms" );
3251

Raymond Knopp's avatar
 
Raymond Knopp committed
3252 3253
    printf("Scope thread created, ret=%d\n",ret);
  }
3254

3255 3256 3257
#endif

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3258 3259
  ret = pthread_create(&thread3, NULL, emos_thread, NULL);
  printf("EMOS thread created, ret=%d\n",ret);
jiangx's avatar
jiangx committed
3260 3261
  ret = pthread_create(&thread4, NULL, gps_thread, NULL);
  printf("GPS thread created, ret=%d\n",ret);
3262 3263
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3264
  rt_sleep_ns(10*FRAME_PERIOD);
3265 3266

#ifndef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3267
  pthread_attr_init (&attr_dlsch_threads);
3268
  pthread_attr_setstacksize(&attr_dlsch_threads,4*PTHREAD_STACK_MIN);
3269

3270
  pthread_attr_init (&attr_UE_thread);
3271
  pthread_attr_setstacksize(&attr_UE_thread,8192);//5*PTHREAD_STACK_MIN);
3272

3273
#ifndef LOWLATENCY
3274 3275
  sched_param_UE_thread.sched_priority = sched_get_priority_max(SCHED_FIFO);
  pthread_attr_setschedparam(&attr_UE_thread,&sched_param_UE_thread);
3276
  sched_param_dlsch.sched_priority = sched_get_priority_max(SCHED_FIFO); //OPENAIR_THREAD_PRIORITY;
Raymond Knopp's avatar
 
Raymond Knopp committed
3277 3278
  pthread_attr_setschedparam  (&attr_dlsch_threads, &sched_param_dlsch);
  pthread_attr_setschedpolicy (&attr_dlsch_threads, SCHED_FIFO);
3279
  printf("Setting eNB_thread FIFO scheduling policy with priority %d \n", sched_param_dlsch.sched_priority);
3280
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3281

3282 3283
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3284 3285
  // start the main thread
  if (UE_flag == 1) {
3286
    printf("Intializing UE Threads ...\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3287
    init_UE_threads();
3288 3289 3290 3291 3292
#ifdef DLSCH_THREAD
    init_rx_pdsch_thread();
    rt_sleep_ns(FRAME_PERIOD/10);
    init_dlsch_threads();
#endif
3293

3294
    sleep(1);
3295
#ifdef RTAI
3296
    main_ue_thread = rt_thread_create(UE_thread, NULL, 100000000);
3297
#else
3298
    error_code = pthread_create(&main_ue_thread, &attr_UE_thread, UE_thread, NULL);
3299

Raymond Knopp's avatar
 
Raymond Knopp committed
3300 3301 3302
    if (error_code!= 0) {
      LOG_D(HW,"[lte-softmodem.c] Could not allocate UE_thread, error %d\n",error_code);
      return(error_code);
3303
    } else {
3304 3305
      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
3306
    }
3307

3308
#endif
3309
    printf("UE threads created\n");
3310 3311 3312 3313 3314 3315 3316 3317 3318 3319
#ifdef USE_MME

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

#endif



3320
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
3321 3322
    if (multi_thread>0) {
      init_eNB_proc();
3323
      sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3324 3325
      LOG_D(HW,"[lte-softmodem.c] eNB threads created\n");
    }
3326

3327
    printf("Creating main eNB_thread \n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3328
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3329
    main_eNB_thread = rt_thread_create(eNB_thread, NULL, PTHREAD_STACK_MIN);
Raymond Knopp's avatar
 
Raymond Knopp committed
3330
#else
3331
    error_code = pthread_create( &main_eNB_thread, &attr_dlsch_threads, eNB_thread, NULL );
3332

Raymond Knopp's avatar
 
Raymond Knopp committed
3333 3334 3335
    if (error_code!= 0) {
      LOG_D(HW,"[lte-softmodem.c] Could not allocate eNB_thread, error %d\n",error_code);
      return(error_code);
3336
    } else {
3337 3338
      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
3339
    }
3340

Raymond Knopp's avatar
 
Raymond Knopp committed
3341 3342
#endif
  }
3343

Raymond Knopp's avatar
 
Raymond Knopp committed
3344
  // Sleep to allow all threads to setup
Raymond Knopp's avatar
 
Raymond Knopp committed
3345
  sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3346

3347

3348

3349
#ifndef EXMIMO
3350

Raymond Knopp's avatar
 
Raymond Knopp committed
3351
#ifndef USRP_DEBUG
3352
  if (mode!=loop_through_memory)
navid's avatar
navid committed
3353 3354 3355
    if (openair0.trx_start_func(&openair0) != 0 ) 
      LOG_E(HW,"Could not start the device\n");

Raymond Knopp's avatar
 
Raymond Knopp committed
3356
#endif
3357

3358 3359
#endif

3360
  printf("Sending sync to all threads\n");
3361

Raymond Knopp's avatar
 
Raymond Knopp committed
3362
  pthread_mutex_lock(&sync_mutex);
3363
  sync_var=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3364 3365
  pthread_cond_broadcast(&sync_cond);
  pthread_mutex_unlock(&sync_mutex);
3366

Raymond Knopp's avatar
 
Raymond Knopp committed
3367 3368 3369
  // wait for end of program
  printf("TYPE <CTRL-C> TO TERMINATE\n");
  //getchar();
3370 3371

#if defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
3372 3373
  printf("Entering ITTI signals handler\n");
  itti_wait_tasks_end();
3374
  oai_exit=1;
3375
#else
3376

Raymond Knopp's avatar
 
Raymond Knopp committed
3377 3378
  while (oai_exit==0)
    rt_sleep_ns(FRAME_PERIOD);
3379

3380
#endif
3381

Raymond Knopp's avatar
 
Raymond Knopp committed
3382
  // stop threads
3383
#ifdef XFORMS
Raymond Knopp's avatar
 
Raymond Knopp committed
3384
  printf("waiting for XFORMS thread\n");
3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398

  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++) {
3399 3400 3401 3402
	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
3403
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
3404
    }
3405 3406
  }

3407 3408
#endif

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3411 3412
  // cleanup
  if (UE_flag == 1) {
3413
#ifdef EXMIMO
3414
#ifdef RTAI
3415
    rt_thread_join(main_ue_thread);
3416
#else
3417
    pthread_join(main_ue_thread,&status);
3418 3419
#endif
#ifdef DLSCH_THREAD
Raymond Knopp's avatar
 
Raymond Knopp committed
3420 3421
    cleanup_dlsch_threads();
    cleanup_rx_pdsch_thread();
3422
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3423
#endif
3424
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
3425
#ifdef DEBUG_THREADS
Raymond Knopp's avatar
 
Raymond Knopp committed
3426
    printf("Joining eNB_thread ...");
Raymond Knopp's avatar
 
Raymond Knopp committed
3427
#endif
3428
#ifdef RTAI
3429
    rt_thread_join(main_eNB_thread);
3430
#else
3431 3432
    int *eNB_thread_status_p;
    int result = pthread_join( main_eNB_thread, (void**)&eNB_thread_status_p );
Raymond Knopp's avatar
 
Raymond Knopp committed
3433
#ifdef DEBUG_THREADS
3434

3435
    if (result != 0) {
3436
      printf( "\nError joining main_eNB_thread.\n" );
3437
    } else {
3438 3439 3440 3441 3442
      if (eNB_thread_status_p) {
        printf( "status %d\n", *eNB_thread_status_p );
      } else {
        printf( "The thread was killed. No status available.\n");
      }
3443
    }
3444

3445 3446
#else
    UNUSED(result);
3447 3448
#endif // DEBUG_THREADS
#endif // RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3449

Raymond Knopp's avatar
 
Raymond Knopp committed
3450 3451 3452
    if (multi_thread>0) {
      printf("Killing eNB processing threads\n");
      kill_eNB_proc();
Raymond Knopp's avatar
 
Raymond Knopp committed
3453

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

3457

3458
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3459
  stop_rt_timer();
3460
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3461 3462
  pthread_cond_destroy(&sync_cond);
  pthread_mutex_destroy(&sync_mutex);
3463

3464

3465
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3466
  printf("stopping card\n");
3467
  openair0_stop(0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3468 3469
  printf("closing openair0_lib\n");
  openair0_close();
navid's avatar
navid committed
3470 3471
#else
  openair0.trx_end_func(&openair0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3472
#endif
3473 3474

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3475 3476 3477
  printf("waiting for EMOS thread\n");
  pthread_cancel(thread3);
  pthread_join(thread3,&status);
jiangx's avatar
jiangx committed
3478 3479 3480
  printf("waiting for GPS thread\n");
  pthread_cancel(thread4);
  pthread_join(thread4,&status);
3481 3482 3483
#endif

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3484 3485
  error_code = rtf_destroy(CHANSOUNDER_FIFO_MINOR);
  printf("[OPENAIR][SCHED][CLEANUP] EMOS FIFO closed, error_code %d\n", error_code);
3486 3487
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3488
  if (ouput_vcd)
3489
    VCD_SIGNAL_DUMPER_CLOSE();
3490

3491
  if (opt_enabled == 1)
3492
    terminate_opt();
3493

Raymond Knopp's avatar
 
Raymond Knopp committed
3494
  logClean();
3495

Raymond Knopp's avatar
 
Raymond Knopp committed
3496 3497
  return 0;
}
3498 3499


3500 3501 3502
/* 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
3503
   antennas are mapped to successive RF chains on the same card. */
3504 3505
int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs])
{
3506

3507
  int i, CC_id;
3508
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3509
  uint16_t N_TA_offset = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3510 3511
#else
  int j;
Raymond Knopp's avatar
 
Raymond Knopp committed
3512
#endif
3513
  LTE_DL_FRAME_PARMS *frame_parms;
3514

Raymond Knopp's avatar
 
Raymond Knopp committed
3515

3516 3517
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    if (phy_vars_eNB[CC_id]) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3518 3519
      frame_parms = &(phy_vars_eNB[CC_id]->lte_frame_parms);
      printf("setup_eNB_buffers: frame_parms = %p\n",frame_parms);
3520
    } else {
3521 3522
      printf("phy_vars_eNB[%d] not initialized\n", CC_id);
      return(-1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3523
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3524

3525
#ifndef EXMIMO
3526

3527 3528
    if (frame_parms->frame_type == TDD) {
      if (frame_parms->N_RB_DL == 100)
3529
        N_TA_offset = 624;
3530
      else if (frame_parms->N_RB_DL == 50)
3531
        N_TA_offset = 624/2;
3532
      else if (frame_parms->N_RB_DL == 25)
3533
        N_TA_offset = 624/4;
Raymond Knopp's avatar
 
Raymond Knopp committed
3534
    }
3535

Raymond Knopp's avatar
 
Raymond Knopp committed
3536
#endif
3537 3538


3539 3540 3541



Raymond Knopp's avatar
 
Raymond Knopp committed
3542
    // replace RX signal buffers with mmaped HW versions
3543
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3544 3545 3546
    openair0_cfg[CC_id].tx_num_channels = 0;
    openair0_cfg[CC_id].rx_num_channels = 0;

3547
    for (i=0; i<frame_parms->nb_antennas_rx; i++) {
3548 3549 3550
      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];
3551

3552
      if (openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i]) {
3553 3554 3555 3556 3557 3558
        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++;
3559
      }
3560

3561
      printf("rxdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]);
3562 3563 3564 3565

      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;
3566
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
3567
    }
3568 3569

    for (i=0; i<frame_parms->nb_antennas_tx; i++) {
3570 3571 3572
      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];
3573

3574
      if (openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i]) {
3575 3576 3577 3578 3579 3580
        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++;
3581
      }
3582

3583
      printf("txdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3584 3585 3586 3587

      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;
3588
      }
3589
    }
3590

3591
#else // not EXMIMO
3592 3593 3594
    rxdata = (int32_t**)malloc16(frame_parms->nb_antennas_rx*sizeof(int32_t*));
    txdata = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*));

3595
    for (i=0; i<frame_parms->nb_antennas_rx; i++) {
3596
      free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]);
3597
      rxdata[i] = (int32_t*)(32 + malloc16(32+openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation
3598
      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
3599
      memset(rxdata[i], 0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t));
3600
      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);
3601
      
Raymond Knopp's avatar
 
Raymond Knopp committed
3602
    }
3603 3604

    for (i=0; i<frame_parms->nb_antennas_tx; i++) {
3605
      free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3606
      txdata[i] = (int32_t*)(32 + malloc16(32 + openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation
3607
      phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i] = txdata[i];
3608
      memset(txdata[i],0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t));
3609
      printf("txdata[%d] @ %p\n", i, phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3610

Raymond Knopp's avatar
 
Raymond Knopp committed
3611
    }
3612

Raymond Knopp's avatar
 
Raymond Knopp committed
3613
#endif
3614
  }
3615

3616
  return(0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3617
}
3618

3619
void reset_opp_meas(void) {
3620 3621 3622
  int sfn;
  reset_meas(&softmodem_stats_mt);
  reset_meas(&softmodem_stats_hw);
3623
  
3624 3625 3626 3627 3628 3629
  for (sfn=0; sfn < 10; sfn++) {
    reset_meas(&softmodem_stats_tx_sf[sfn]);
    reset_meas(&softmodem_stats_rx_sf[sfn]);
  }
}

3630 3631
void print_opp_meas(void) {

3632 3633 3634
  int sfn=0;
  print_meas(&softmodem_stats_mt, "Main ENB Thread", NULL, NULL);
  print_meas(&softmodem_stats_hw, "HW Acquisation", NULL, NULL);
3635
  
3636 3637 3638 3639 3640
  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);
  }
}
3641 3642