lte-softmodem.c 110 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 24
   Contact Information
   OpenAirInterface Admin: openair_admin@eurecom.fr
   OpenAirInterface Tech : openair_tech@eurecom.fr
   OpenAirInterface Dev  : openair4g-devel@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 49 50
#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 <sys/stat.h>
#include <fcntl.h>
#include <sched.h>
51
#include <linux/sched.h>
52 53 54
#include <signal.h>
#include <execinfo.h>
#include <getopt.h>
55
#include <syscall.h>
56
#include <pthread.h>  //  for gettid
57 58

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

61
#include "assertions.h"
62
#include "msc.h"
63 64 65

#ifdef EMOS
#include <gps.h>
jiangx's avatar
jiangx committed
66
struct gps_fix_t dummy_gps_data;
67 68 69
#endif

#include "PHY/types.h"
70

71
#include "PHY/defs.h"
72
#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
73
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
74

75
#ifdef EXMIMO
76
#include "openair0_lib.h"
Raymond Knopp's avatar
 
Raymond Knopp committed
77 78 79 80
#else
#include "../../ARCH/COMMON/common_lib.h"
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
81
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
82 83 84

#include "PHY/vars.h"
#include "MAC_INTERFACE/vars.h"
85
//#include "SCHED/defs.h"
86 87 88 89 90 91 92 93 94 95 96 97
#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"
98
#include "LAYER2/MAC/proto.h"
99 100 101 102 103 104 105 106 107
#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
108
#include "UTIL/OTG/otg_tx.h"
109
#include "UTIL/OTG/otg_externs.h"
110 111
#include "UTIL/MATH/oml.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
112
#include "UTIL/OPT/opt.h"
113
#include "enb_config.h"
Navid Nikaein's avatar
Navid Nikaein committed
114
//#include "PHY/TOOLS/time_meas.h"
115

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
116 117 118 119
#ifndef OPENAIR2
#include "UTIL/OTG/otg_vars.h"
#endif

120 121
#if defined(ENABLE_ITTI)
# include "intertask_interface_init.h"
122
# include "create_tasks.h"
123 124
# if defined(ENABLE_USE_MME)
#   include "s1ap_eNB.h"
125
#ifdef PDCP_USE_NETLINK
126 127
#   include "SIMULATION/ETH_TRANSPORT/proto.h"
#endif
128
# endif
129 130
#endif

131 132 133
#ifdef XFORMS
#include "PHY/TOOLS/lte_phy_scope.h"
#include "stats.h"
134 135 136 137 138
#endif

#define FRAME_PERIOD    100000000ULL
#define DAQ_PERIOD      66667ULL

Florian Kaltenberger's avatar
Florian Kaltenberger committed
139
//#define DEBUG_THREADS 1
Raymond Knopp's avatar
 
Raymond Knopp committed
140

Raymond Knopp's avatar
 
Raymond Knopp committed
141 142
//#define USRP_DEBUG 1

143
struct timing_info_t {
144 145 146 147
  //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;
148 149 150
} timing_info;


Raymond Knopp's avatar
 
Raymond Knopp committed
151

152
openair0_config_t openair0_cfg[MAX_CARDS];
Raymond Knopp's avatar
 
Raymond Knopp committed
153

Raymond Knopp's avatar
 
Raymond Knopp committed
154 155
int32_t **rxdata;
int32_t **txdata;
156 157
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]);
158

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

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

242
openair0_rf_map rf_map[MAX_NUM_CCs];
243

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

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


Raymond Knopp's avatar
 
Raymond Knopp committed
254
#ifdef EXMIMO
255 256 257 258
#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
259 260
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}};
261
#endif
262
// these are for EXMIMO2 target only
263
/*
Raymond Knopp's avatar
 
Raymond Knopp committed
264 265 266
  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};
267
 */
268
// these are for EXMIMO2 card 39
269 270 271 272 273 274
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};
275 276 277
#if MAX_NUM_CCs == 1
rx_gain_t                rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain}};
#else
278
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}};
279
#endif
Lionel Gauthier's avatar
Lionel Gauthier committed
280
#else
kortke's avatar
kortke committed
281 282
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
283
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
284

Raymond Knopp's avatar
 
Raymond Knopp committed
285 286
double sample_rate=30.72e6;
double bw = 14e6;
287

288
static int                      tx_max_power[MAX_NUM_CCs]; /* =  {0,0}*/;
289

290
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
291 292 293
char ref[128] = "internal";
char channels[128] = "0";

Raymond Knopp's avatar
 
Raymond Knopp committed
294 295
unsigned int samples_per_frame = 307200;
unsigned int tx_forward_nsamps;
Raymond Knopp's avatar
 
Raymond Knopp committed
296 297 298
int tx_delay;

#endif
299 300

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

Raymond Knopp's avatar
 
Raymond Knopp committed
314
static LTE_DL_FRAME_PARMS      *frame_parms[MAX_NUM_CCs];
315

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

Raymond Knopp's avatar
 
Raymond Knopp committed
322

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

Raymond Knopp's avatar
 
Raymond Knopp committed
331

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
360 361 362

#ifdef ETHERNET
char rrh_eNB_ip[20] = "127.0.0.1";
Raymond Knopp's avatar
Raymond Knopp committed
363
int rrh_eNB_port = 50000;
Raymond Knopp's avatar
 
Raymond Knopp committed
364
char *rrh_UE_ip = "127.0.0.1";
365
int rrh_UE_port = 51000;
Raymond Knopp's avatar
 
Raymond Knopp committed
366 367 368
#endif

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

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

381
#ifdef LOWLATENCY
382 383
int sched_setattr(pid_t pid, const struct sched_attr *attr, unsigned int flags)
{
384 385 386 387 388

  return syscall(__NR_sched_setattr, pid, attr, flags);
}


389 390
int sched_getattr(pid_t pid,struct sched_attr *attr,unsigned int size, unsigned int flags)
{
391 392 393

  return syscall(__NR_sched_getattr, pid, attr, size, flags);
}
394
#endif
395
#if !defined(ENABLE_ITTI)
396 397 398 399 400 401 402 403
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);
404

405 406 407 408
    // print out all the frames to stderr
    fprintf(stderr, "Error: signal %d:\n", sig);
    backtrace_symbols_fd(array, size, 2);
    exit(-1);
409 410
  } else {
    printf("trying to exit gracefully...\n");
411
    oai_exit = 1;
412 413
  }
}
414
#endif
415 416 417 418 419 420 421 422 423 424 425 426 427 428 429
#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
430 431
  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");
432 433 434
  printf("  --no-L2-connect bypass L2 and upper layers\n");
  printf("  --ue_rxgain set UE RX gain\n");
  printf("  --ue_txgain set UE tx gain\n");
435
  printf("  --ue_scan_carrier set UE to scan around carrier\n");
436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453
  printf("  -C Set the downlink frequecny for all Component carrier\n");
  printf("  -d Enable soft scope and L1 and L2 stats (Xforms)\n");
  printf("  -F Calibrate the EXMIMO borad, available files: exmimo2_2arxg.lime exmimo2_2brxg.lime \n");
  printf("  -g Set the global log level, valide options: (9:trace, 8/7:debug, 6:info, 4:warn, 3:error)\n");
  printf("  -G Set the global log level \n");
  printf("  -h provides this help message!\n");
  printf("  -K Generate ITTI analyzser logs (similar to wireshark logs but with more details)\n");
  printf("  -m Set the maximum downlink MCS\n");
  printf("  -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");
  printf("  -R Set the PRB, valid values: 6, 25, 50, 100  \n");    
  printf("  -S Skip the missed slots/subframes \n");    
  printf("  -t Set the maximum uplink MCS\n");
  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);    
454

455
}
456 457
void exit_fun(const char* s)
{
458
  if (s != NULL) {
459
    printf("%s %s() Exiting OAI softmodem: %s\n",__FILE__, __FUNCTION__, s);
460 461 462 463 464
  }

  oai_exit = 1;

#if defined(ENABLE_ITTI)
Florian Kaltenberger's avatar
Florian Kaltenberger committed
465
  sleep(1); //allow lte-softmodem threads to exit first
466
  itti_terminate_tasks (TASK_UNKNOWN);
467
#endif
468 469 470 471 472 473

  //rt_sleep_ns(FRAME_PERIOD);

  //exit (-1);
}

Raymond Knopp's avatar
 
Raymond Knopp committed
474 475
static int latency_target_fd = -1;
static int32_t latency_target_value = 0;
476
/* Latency trick - taken from cyclictest.c
Raymond Knopp's avatar
 
Raymond Knopp committed
477 478 479 480 481 482 483 484 485
 * if the file /dev/cpu_dma_latency exists,
 * open it and write a zero into it. This will tell
 * the power management system not to transition to
 * a high cstate (in fact, the system acts like idle=poll)
 * When the fd to /dev/cpu_dma_latency is closed, the behavior
 * goes back to the system default.
 *
 * Documentation/power/pm_qos_interface.txt
 */
Raymond Knopp's avatar
 
Raymond Knopp committed
486 487 488 489
static void set_latency_target(void)
{
  struct stat s;
  int ret;
490

Raymond Knopp's avatar
 
Raymond Knopp committed
491 492
  if (stat("/dev/cpu_dma_latency", &s) == 0) {
    latency_target_fd = open("/dev/cpu_dma_latency", O_RDWR);
493

Raymond Knopp's avatar
 
Raymond Knopp committed
494 495
    if (latency_target_fd == -1)
      return;
496

Raymond Knopp's avatar
 
Raymond Knopp committed
497
    ret = write(latency_target_fd, &latency_target_value, 4);
498

Raymond Knopp's avatar
 
Raymond Knopp committed
499 500 501 502 503
    if (ret == 0) {
      printf("# error setting cpu_dma_latency to %d!: %s\n", latency_target_value, strerror(errno));
      close(latency_target_fd);
      return;
    }
504

Raymond Knopp's avatar
 
Raymond Knopp committed
505 506 507
    printf("# /dev/cpu_dma_latency set to %dus\n", latency_target_value);
  }
}
508

509
#ifdef XFORMS
510

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

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

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

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

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

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

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

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

557
# ifdef ENABLE_XFORMS_WRITE_STATS
558 559

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

564
#endif
565

Raymond Knopp's avatar
 
Raymond Knopp committed
566 567
  while (!oai_exit) {
    if (UE_flag==1) {
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
568
      len = dump_ue_stats (PHY_vars_UE_g[0][0], stats_buffer, 0, mode,rx_input_level_dBm);
Raymond Knopp's avatar
 
Raymond Knopp committed
569
      fl_set_object_label(form_stats->stats_text, stats_buffer);
570

571 572 573 574 575
      phy_scope_UE(form_ue[0],
                   PHY_vars_UE_g[0][0],
                   0,
                   0,7);

Raymond Knopp's avatar
 
Raymond Knopp committed
576
    } else {
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
577 578
#ifdef OPENAIR2
      len = dump_eNB_l2_stats (stats_buffer, 0);
579
      fl_set_object_label(form_stats_l2->stats_text, stats_buffer);
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
580 581
#endif
      len = dump_eNB_stats (PHY_vars_eNB_g[0][0], stats_buffer, 0);
582

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

586 587
      fl_set_object_label(form_stats->stats_text, stats_buffer);

588
      for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
589 590 591 592 593
	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
594
      }
595

596
    }
597

Raymond Knopp's avatar
 
Raymond Knopp committed
598
    //printf("doing forms\n");
Florian Kaltenberger's avatar
Florian Kaltenberger committed
599 600
    //usleep(100000); // 100 ms
    sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
601
  }
602

603
  //  printf("%s",stats_buffer);
604

605
# ifdef ENABLE_XFORMS_WRITE_STATS
606

607 608 609 610 611 612
  if (UE_flag==1) {
    if (UE_stats) {
      rewind (UE_stats);
      fwrite (stats_buffer, 1, len, UE_stats);
      fclose (UE_stats);
    }
613
  } else {
614 615 616 617 618 619
    if (eNB_stats) {
      rewind (eNB_stats);
      fwrite (stats_buffer, 1, len, eNB_stats);
      fclose (eNB_stats);
    }
  }
620

621
# endif
622

Raymond Knopp's avatar
 
Raymond Knopp committed
623
  pthread_exit((void*)arg);
624 625 626 627 628 629
}
#endif

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

jiangx's avatar
jiangx committed
630 631 632 633 634 635 636 637
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;

638
  sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
jiangx's avatar
jiangx committed
639
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
640

jiangx's avatar
jiangx committed
641 642 643
  printf("GPS thread has priority %d\n",sched_param.sched_priority);

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

jiangx's avatar
jiangx committed
645 646
#if GPSD_API_MAJOR_VERSION>=5
  ret = gps_open("127.0.0.1","2947",gps_data_ptr);
647

jiangx's avatar
jiangx committed
648 649 650
  if (ret!=0)
#else
  gps_data_ptr = gps_open("127.0.0.1","2947");
651 652

  if (gps_data_ptr == NULL)
jiangx's avatar
jiangx committed
653
#endif
654 655 656 657 658
  {
    printf("[EMOS] Could not open GPS\n");
    pthread_exit((void*)arg);
  }

jiangx's avatar
jiangx committed
659 660 661 662 663
#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
664 665 666 667
  {
    printf("[EMOS] Error sending command to GPS\n");
    pthread_exit((void*) arg);
  } else
jiangx's avatar
jiangx committed
668 669
    printf("[EMOS] Opened GPS, gps_data=%p\n", gps_data_ptr);

670 671 672

  while (!oai_exit) {
    printf("[EMOS] polling data from gps\n");
jiangx's avatar
jiangx committed
673
#if GPSD_API_MAJOR_VERSION>=5
674 675 676

    if (gps_waiting(gps_data_ptr,500)) {
      if (gps_read(gps_data_ptr) <= 0) {
jiangx's avatar
jiangx committed
677
#else
678 679 680 681 682 683 684 685

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

  pthread_exit((void*) arg);

}

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

jiangx's avatar
jiangx committed
712
  int channel_buffer_size,ret;
713

714 715 716
  time_t timer;
  struct tm *now;

717
  struct sched_param sched_param;
718 719

  sched_param.sched_priority = sched_get_priority_max(SCHED_FIFO)-1;
720
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
721

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

724 725 726 727 728 729 730 731 732 733 734 735
  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;

736 737 738 739
  if (fifo2file_buffer == NULL) {
    printf("[EMOS] Cound not allocate memory for fifo2file_buffer\n");
    exit(EXIT_FAILURE);
  }
740

741 742 743 744
  if ((fifo = open(CHANSOUNDER_FIFO_DEV, O_RDONLY)) < 0) {
    fprintf(stderr, "[EMOS] Error opening the fifo\n");
    exit(EXIT_FAILURE);
  }
745 746 747 748 749


  time(&starttime_tmp);
  localtime_r(&starttime_tmp,&starttime);
  snprintf(dumpfile_name,1024,"/tmp/%s_data_%d%02d%02d_%02d%02d%02d.EMOS",
750 751
           (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);
752 753

  dumpfile_id = fopen(dumpfile_name,"w");
754 755 756 757 758

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


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

763 764 765 766 767 768 769
  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);
770

771 772 773 774
    if (bytes<=0) {
      usleep(100);
      continue;
    }
775

776 777 778
    if (bytes != channel_buffer_size) {
      printf("[EMOS] ERROR! Only got %d bytes instead of %d!\n",bytes,channel_buffer_size);
    }
779

780 781 782 783 784 785
    /*
    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);
    */
786

787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807
    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
808

809 810 811 812
      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);
      }
813
    }
814 815
  }

816 817 818
  free(fifo2file_buffer);
  fclose(dumpfile_id);
  close(fifo);
819

820 821 822 823 824
  pthread_exit((void*) arg);

}
#endif

825 826


827
#if defined(ENABLE_ITTI)
828 829 830 831 832
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[] = {".    ", "..   ", "...  ", ".... ", ".....",
833 834
                                " ....", "  ...", "   ..", "    .", "     "
                               };
835 836 837 838 839 840 841
    int i = 0;

    while ((!oai_exit) && (*start_flag == 0)) {
      LOG_N(EMU, message, indicator[i]);
      i = (i + 1) % (sizeof(indicator) / sizeof(indicator[0]));
      usleep(200000);
    }
842

843 844 845 846 847
    LOG_D(EMU,"\n");
  }
}
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
848
#if defined(ENABLE_ITTI)
849
void *l2l1_task(void *arg)
850
{
Raymond Knopp's avatar
 
Raymond Knopp committed
851 852 853 854 855
  MessageDef *message_p = NULL;
  int         result;

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
856

Raymond Knopp's avatar
 
Raymond Knopp committed
857 858
  if (UE_flag == 0) {
    /* Wait for the initialize message */
859
    printf("Wait for the ITTI initialize message\n");
860
    do {
Raymond Knopp's avatar
 
Raymond Knopp committed
861
      if (message_p != NULL) {
862 863
        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
864
      }
865

866 867 868
      itti_receive_msg (TASK_L2L1, &message_p);

      switch (ITTI_MSG_ID(message_p)) {
Raymond Knopp's avatar
 
Raymond Knopp committed
869
      case INITIALIZE_MESSAGE:
870 871 872 873
        /* 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
874 875

      case TERMINATE_MESSAGE:
876 877 878 879
        printf("received terminate message\n");
        oai_exit=1;
        itti_exit_task ();
        break;
Raymond Knopp's avatar
 
Raymond Knopp committed
880 881

      default:
882 883
        LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
        break;
884
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
885
    } while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE);
886

Raymond Knopp's avatar
 
Raymond Knopp committed
887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907
    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;
908

Raymond Knopp's avatar
 
Raymond Knopp committed
909 910 911 912 913 914 915 916 917 918 919
    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);
920
  } while(!oai_exit);
921

Raymond Knopp's avatar
 
Raymond Knopp committed
922
  return NULL;
923 924 925
}
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
926

927 928
void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
929 930 931 932

  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
933
  int slot_sizeF = (phy_vars_eNB->lte_frame_parms.ofdm_symbol_size)*
934
                   ((phy_vars_eNB->lte_frame_parms.Ncp==1) ? 6 : 7);
Raymond Knopp's avatar
 
Raymond Knopp committed
935 936

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
944

Raymond Knopp's avatar
 
Raymond Knopp committed
945
    for (aa=0; aa<phy_vars_eNB->lte_frame_parms.nb_antennas_tx; aa++) {
946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967
      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,
                     phy_vars_eNB->lte_frame_parms.log2_symbol_size,
                     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),
                     phy_vars_eNB->lte_frame_parms.log2_symbol_size,
                     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));
        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
968
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
969 970

      for (i=0; i<phy_vars_eNB->lte_frame_parms.samples_per_tti; i++) {
971 972 973 974 975 976 977 978 979
        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
980
#ifdef EXMIMO
981
          ((short*)dummy_tx_b)[2*i]<<4;
Raymond Knopp's avatar
 
Raymond Knopp committed
982
#else
983
          ((short*)dummy_tx_b)[2*i]<<5;
Raymond Knopp's avatar
 
Raymond Knopp committed
984
#endif
985
        ((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[1]=
Raymond Knopp's avatar
 
Raymond Knopp committed
986
#ifdef EXMIMO
987
          ((short*)dummy_tx_b)[2*i+1]<<4;
Raymond Knopp's avatar
 
Raymond Knopp committed
988
#else
989
          ((short*)dummy_tx_b)[2*i+1]<<5;
Raymond Knopp's avatar
 
Raymond Knopp committed
990
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
991 992 993 994 995
      }
    }
  }
}

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

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

  eNB_proc_t *proc = (eNB_proc_t*)param;
1017 1018 1019 1020 1021 1022
  FILE  *tx_time_file;
  char tx_time_name[101];
  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");
  }
1023 1024 1025
  // set default return value
  eNB_thread_tx_status[proc->subframe] = 0;

Raymond Knopp's avatar
 
Raymond Knopp committed
1026 1027
#ifdef RTAI
  RT_TASK *task;
1028
  char task_name[8];
Raymond Knopp's avatar
 
Raymond Knopp committed
1029

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1043
#else
1044
#ifdef LOWLATENCY
1045 1046 1047
  struct sched_attr attr;
  unsigned int flags = 0;

1048 1049 1050 1051
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1052

1053 1054 1055
  // This creates a 1ms reservation every 10ms period
  attr.sched_policy   = SCHED_DEADLINE;
  attr.sched_runtime  = 0.9 *  1000000; // each tx thread requires 1ms to finish its job
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1056 1057
  attr.sched_deadline = 1   *  1000000; // each tx thread will finish within 1ms
  attr.sched_period   = 1   * 10000000; // each tx thread has a period of 10ms from the starting point
1058

1059 1060 1061 1062
  if (sched_setattr(0, &attr, flags) < 0 ) {
    perror("[SCHED] eNB tx thread: sched_setattr failed\n");
    return &eNB_thread_tx_status[proc->subframe];
  }
1063

1064
  LOG_I( HW, "[SCHED] eNB TX deadline thread %d(tid %ld) started on CPU %d\n", proc->subframe, gettid(), sched_getcpu() );
1065
#else
1066
  LOG_I( HW, "[SCHED][eNB] TX thread %d started on CPU %d TID %d\n", proc->subframe, sched_getcpu(),gettid() );
1067 1068
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
1069 1070 1071 1072 1073 1074 1075 1076
#endif

  mlockall(MCL_CURRENT | MCL_FUTURE);

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

1077
  while (!oai_exit) {
1078

1079
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe), 0 );
1080

1081
    if (pthread_mutex_lock(&proc->mutex_tx) != 0) {
1082
      LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc %d\n", proc->subframe );
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1083
      exit_fun("nothing to add");
1084
      break;
1085
    }
1086

1087
    while (proc->instance_cnt_tx < 0) {
1088 1089 1090
      // 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
1091
    }
1092

1093 1094 1095 1096 1097
    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
1098

1099 1100
    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 );
1101 1102 1103
    start_meas( &softmodem_stats_tx_sf[proc->subframe] );

    if (oai_exit) break;
1104

1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121
    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;
      }
      /* wait for our turn */
      while (sync_phy_proc[proc->subframe].phy_proc_CC_id != proc->CC_id) {
        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
1122

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

1125 1126 1127 1128 1129 1130 1131 1132 1133
      /* we're done, let the next one proceed */
      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) {
        LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX proc %d\n", proc->subframe);
        exit_fun("nothing to add");
        break;
      }
1134
    }
1135

1136
    do_OFDM_mod_rt( proc->subframe_tx, PHY_vars_eNB_g[0][proc->CC_id] );
1137

1138 1139 1140 1141 1142
    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
1143

1144 1145 1146 1147 1148 1149 1150 1151 1152
    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++;
1153

1154 1155 1156
    if (proc->frame_tx==1024)
      proc->frame_tx=0;

1157 1158 1159
    stop_meas( &softmodem_stats_tx_sf[proc->subframe] );
    print_meas_now(&softmodem_stats_tx_sf[proc->subframe],"eNB_TX_SF",proc->subframe, tx_time_file);

1160 1161 1162
  }

  stop_meas( &softmodem_stats_tx_sf[proc->subframe] );
1163
  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
1164

Raymond Knopp's avatar
 
Raymond Knopp committed
1165 1166 1167
#ifdef HARD_RT
  rt_make_soft_real_time();
#endif
1168

Raymond Knopp's avatar
 
Raymond Knopp committed
1169
#ifdef DEBUG_THREADS
1170
  printf( "Exiting eNB thread TX %d\n", proc->subframe );
Raymond Knopp's avatar
 
Raymond Knopp committed
1171 1172 1173 1174 1175
#endif
  // clean task
#ifdef RTAI
  rt_task_delete(task);
#endif
1176

1177 1178
  eNB_thread_tx_status[proc->subframe] = 0;
  return &eNB_thread_tx_status[proc->subframe];
Raymond Knopp's avatar
 
Raymond Knopp committed
1179 1180 1181
}


1182 1183 1184 1185 1186 1187 1188 1189 1190 1191
/*!
 * \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
1192
  eNB_proc_t *proc = (eNB_proc_t*)param;
1193

1194 1195
  FILE  *rx_time_file;
  char rx_time_name[101];
Raymond Knopp's avatar
 
Raymond Knopp committed
1196 1197
  int i;

1198 1199 1200 1201
  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");
  }
1202 1203 1204
  // set default return value
  eNB_thread_rx_status[proc->subframe] = 0;

Raymond Knopp's avatar
 
Raymond Knopp committed
1205 1206
#ifdef RTAI
  RT_TASK *task;
1207
  char task_name[8];
Raymond Knopp's avatar
 
Raymond Knopp committed
1208

1209
  sprintf(task_name,"RXC%1dS%1d",proc->CC_id,proc->subframe);
Raymond Knopp's avatar
 
Raymond Knopp committed
1210 1211 1212
  task = rt_task_init_schmod(nam2num(task_name), 0, 0, 0, SCHED_FIFO, 0xF);

  if (task==NULL) {
1213 1214
    LOG_E(PHY,"[SCHED][eNB] Problem starting eNB_proc_RX thread_index %d (%s)!!!!\n",proc->subframe,task_name);
    return 0;
1215
  } else {
1216
    LOG_I(PHY,"[SCHED][eNB] eNB RX thread CC_id %d SF %d started with id %p\n", /*  on CPU %d*/
1217 1218 1219
          proc->CC_id,
          proc->subframe,
          task); /*,rtai_cpuid()*/
Raymond Knopp's avatar
 
Raymond Knopp committed
1220
  }
1221

Raymond Knopp's avatar
 
Raymond Knopp committed
1222
#else
1223
#ifdef LOWLATENCY
1224 1225 1226
  struct sched_attr attr;
  unsigned int flags = 0;

1227 1228 1229 1230
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1231

Navid Nikaein's avatar
Navid Nikaein committed
1232
  /* This creates a 2ms reservation every 10ms period*/
1233
  attr.sched_policy = SCHED_DEADLINE;
1234
  attr.sched_runtime  = 0.9 *  1000000; // each rx thread must finish its job in the worst case in 2ms
1235
  attr.sched_deadline = 2   *  1000000; // each rx thread will finish within 2ms
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1236
  attr.sched_period   = 1   * 10000000; // each rx thread has a period of 10ms from the starting point
1237 1238

  if (sched_setattr(0, &attr, flags) < 0 ) {
1239
    perror("[SCHED] eNB RX sched_setattr failed\n");
1240
    return &eNB_thread_rx_status[proc->subframe];
1241
  }
1242

1243
  LOG_I( HW, "[SCHED] eNB RX deadline thread %d(id %ld) started on CPU %d\n", proc->subframe, gettid(), sched_getcpu() );
1244
#else
1245
  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
1246
#endif
1247
#endif // RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
1248 1249 1250 1251 1252 1253 1254

  mlockall(MCL_CURRENT | MCL_FUTURE);

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

1255
  while (!oai_exit) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1256

1257
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 0 );
1258

Raymond Knopp's avatar
 
Raymond Knopp committed
1259
    if (pthread_mutex_lock(&proc->mutex_rx) != 0) {
1260 1261 1262
      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
1263 1264
    }

1265
    while (proc->instance_cnt_rx < 0) {
1266 1267 1268
      // 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
1269
    }
1270 1271 1272 1273 1274 1275 1276

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

1277 1278
    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 );
1279
    start_meas( &softmodem_stats_rx_sf[proc->subframe] );
1280

Raymond Knopp's avatar
 
Raymond Knopp committed
1281
    if (oai_exit) break;
1282

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

1286
      phy_procedures_eNB_RX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay );
Raymond Knopp's avatar
 
Raymond Knopp committed
1287
    }
1288 1289

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1293
    if (pthread_mutex_lock(&proc->mutex_rx) != 0) {
1294 1295 1296
      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
1297
    }
1298 1299 1300 1301 1302 1303 1304

    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
1305
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1306 1307

    proc->frame_rx++;
1308

Raymond Knopp's avatar
 
Raymond Knopp committed
1309 1310
    if (proc->frame_rx==1024)
      proc->frame_rx=0;
1311

1312 1313 1314
    stop_meas( &softmodem_stats_rx_sf[proc->subframe] );
    print_meas_now(&softmodem_stats_rx_sf[proc->subframe],"eNB_RX_SF",proc->subframe, rx_time_file);

Raymond Knopp's avatar
 
Raymond Knopp committed
1315
  }
1316 1317

  stop_meas( &softmodem_stats_rx_sf[proc->subframe] );
1318
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 0 );
1319

Raymond Knopp's avatar
 
Raymond Knopp committed
1320
#ifdef HARD_RT
Raymond Knopp's avatar
 
Raymond Knopp committed
1321 1322 1323 1324
  rt_make_soft_real_time();
#endif

#ifdef DEBUG_THREADS
1325
  printf( "Exiting eNB thread RX %d\n", proc->subframe );
Raymond Knopp's avatar
 
Raymond Knopp committed
1326 1327 1328 1329
#endif
  // clean task
#ifdef RTAI
  rt_task_delete(task);
Raymond Knopp's avatar
 
Raymond Knopp committed
1330 1331
#endif

1332 1333
  eNB_thread_rx_status[proc->subframe] = 0;
  return &eNB_thread_rx_status[proc->subframe];
Raymond Knopp's avatar
 
Raymond Knopp committed
1334 1335 1336 1337
}



Raymond Knopp's avatar
 
Raymond Knopp committed
1338

1339 1340
void init_eNB_proc(void)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1341
  int i;
Raymond Knopp's avatar
 
Raymond Knopp committed
1342 1343
  int CC_id;

1344 1345 1346 1347
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    for (i=0; i<NUM_ENB_THREADS; i++) {
      // set the stack size
      pthread_attr_init( &attr_eNB_proc_tx[CC_id][i] );
1348

1349
      if (pthread_attr_setstacksize( &attr_eNB_proc_tx[CC_id][i], PTHREAD_STACK_MIN ) != 0)
1350 1351
        perror("[ENB_PROC_TX] setting thread stack size failed\n");

1352
      pthread_attr_init( &attr_eNB_proc_rx[CC_id][i] );
1353

1354
      if (pthread_attr_setstacksize( &attr_eNB_proc_rx[CC_id][i], PTHREAD_STACK_MIN ) != 0)
1355
        perror("[ENB_PROC_RX] setting thread stack size failed\n");
1356

1357
#ifndef LOWLATENCY
1358
      // set the kernel scheduling policy and priority
Raymond Knopp's avatar
 
Raymond Knopp committed
1359 1360 1361 1362 1363 1364
      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);
1365
      printf("Setting OS scheduler to SCHED_FIFO for eNB [cc%d][thread%d] \n",CC_id, i);
1366 1367
#endif

1368 1369 1370
      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
1371
      PHY_vars_eNB_g[0][CC_id]->proc[i].CC_id = CC_id;
1372 1373 1374 1375 1376 1377
      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);
      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] );
1378 1379 1380 1381 1382
      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
1383 1384
      PHY_vars_eNB_g[0][CC_id]->proc[i].frame_tx = 0;
      PHY_vars_eNB_g[0][CC_id]->proc[i].frame_rx = 0;
1385
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
1386 1387
      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
1388
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
1389 1390
      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
1391
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1392
    }
1393 1394


1395
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
1396 1397
    // 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
1398

Raymond Knopp's avatar
 
Raymond Knopp committed
1399
    //PHY_vars_eNB_g[0][CC_id]->proc[0].frame_rx = 1023;
Raymond Knopp's avatar
 
Raymond Knopp committed
1400 1401
    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
1402
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
1403 1404
    // 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
1405
    //    PHY_vars_eNB_g[0][CC_id]->proc[7].frame_tx = 1;
Raymond Knopp's avatar
 
Raymond Knopp committed
1406 1407
    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
1408
    //    PHY_vars_eNB_g[0][CC_id]->proc[0].frame_tx = 1;
Raymond Knopp's avatar
 
Raymond Knopp committed
1409
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1410
  }
1411 1412 1413 1414 1415 1416 1417

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

1420 1421 1422 1423 1424 1425
/*!
 * \brief Terminate eNB TX and RX threads.
 */
void kill_eNB_proc(void)
{
  int *status;
Raymond Knopp's avatar
 
Raymond Knopp committed
1426

1427 1428
  for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++)
    for (int i=0; i<NUM_ENB_THREADS; i++) {
1429

Raymond Knopp's avatar
 
Raymond Knopp committed
1430
#ifdef DEBUG_THREADS
1431
      printf( "Killing TX CC_id %d thread %d\n", CC_id, i );
Raymond Knopp's avatar
 
Raymond Knopp committed
1432
#endif
1433 1434 1435 1436

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1442
#ifdef DEBUG_THREADS
1443

1444 1445 1446 1447 1448 1449 1450 1451 1452
      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" );
        }
      }
1453

1454 1455
#else
      UNUSED(result)
Raymond Knopp's avatar
 
Raymond Knopp committed
1456
#endif
1457

Raymond Knopp's avatar
 
Raymond Knopp committed
1458
#ifdef DEBUG_THREADS
1459
      printf( "Killing RX CC_id %d thread %d\n", CC_id, i );
Raymond Knopp's avatar
 
Raymond Knopp committed
1460
#endif
1461 1462 1463 1464

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

1470 1471
#ifdef DEBUG_THREADS

1472 1473 1474 1475 1476 1477 1478 1479 1480
      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" );
        }
      }
1481

1482 1483
#else
      UNUSED(result)
Raymond Knopp's avatar
 
Raymond Knopp committed
1484
#endif
1485 1486 1487 1488 1489

      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
1490
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1491 1492 1493
}


Raymond Knopp's avatar
 
Raymond Knopp committed
1494 1495


1496

Raymond Knopp's avatar
 
Raymond Knopp committed
1497

1498 1499 1500 1501 1502 1503
/*!
 * \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 )
1504
{
1505 1506
  UNUSED(arg);
  static int eNB_thread_status;
1507

1508
  unsigned char slot;
1509
#ifdef EXMIMO
1510
  slot=0;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1511
  RTIME time_in;
Raymond Knopp's avatar
 
Raymond Knopp committed
1512
  volatile unsigned int *DAQ_MBOX = openair0_daq_cnt();
Raymond Knopp's avatar
 
Raymond Knopp committed
1513 1514
  int mbox_target=0,mbox_current=0;
  int hw_slot,delay_cnt;
Raymond Knopp's avatar
 
Raymond Knopp committed
1515 1516
  int diff;
  int ret;
1517
  int first_run=1;
Raymond Knopp's avatar
 
Raymond Knopp committed
1518
#else
1519 1520 1521
  // the USRP implementation operates on subframes, not slots
  // one subframe consists of one even and one odd slot
  slot = 1;
1522
  int spp;
1523
  int tx_launched = 0;
1524 1525 1526

  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
1527

1528
  int hw_subframe = 0; // 0..NUM_ENB_THREADS-1 => 0..9
1529
  spp = openair0_cfg[0].samples_per_packet;
1530 1531
  unsigned int rx_pos = 0;
  unsigned int tx_pos = spp*tx_delay;
Raymond Knopp's avatar
 
Raymond Knopp committed
1532
#endif
1533
  int CC_id=0;	
1534
  struct timespec trx_time0, trx_time1, trx_time2;
1535

1536
#ifdef RTAI
1537
  RT_TASK* task = rt_task_init_schmod(nam2num("eNBmain"), 0, 0, 0, SCHED_FIFO, 0xF);
1538
#else
1539
#ifdef LOWLATENCY
1540 1541 1542
  struct sched_attr attr;
  unsigned int flags = 0;

Raymond Knopp's avatar
 
Raymond Knopp committed
1543 1544 1545 1546
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1547

Raymond Knopp's avatar
 
Raymond Knopp committed
1548 1549
  /* This creates a .5 ms  reservation */
  attr.sched_policy = SCHED_DEADLINE;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1550
  attr.sched_runtime  = 0.1 * 1000000;
Raymond Knopp's avatar
 
Raymond Knopp committed
1551
  attr.sched_deadline = 0.5 * 1000000;
1552 1553
  attr.sched_period   = 1.0 * 1000000;

Lionel Gauthier's avatar
Lionel Gauthier committed
1554

Raymond Knopp's avatar
 
Raymond Knopp committed
1555 1556 1557 1558
  /* 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");
     }*/
1559

1560
  if (sched_setattr(0, &attr, flags) < 0 ) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1561 1562 1563 1564
    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",
1565
          gettid(),sched_getcpu());
Raymond Knopp's avatar
 
Raymond Knopp committed
1566
  }
1567

1568
#endif
1569 1570
#endif

1571 1572 1573 1574 1575
  // stop early, if an exit is requested
  // FIXME really neccessary?
  if (oai_exit)
    goto eNB_thread_cleanup;

1576
#ifdef RTAI
1577
  printf( "[SCHED][eNB] Started eNB main thread (id %p)\n", task );
Raymond Knopp's avatar
 
Raymond Knopp committed
1578
#else
1579
  printf( "[SCHED][eNB] Started eNB main thread on CPU %d TID %d\n", sched_getcpu(), gettid());
1580 1581 1582
#endif

#ifdef HARD_RT
1583
  rt_make_hard_real_time();
1584 1585
#endif

1586 1587 1588 1589 1590 1591 1592 1593
  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;
1594

1595 1596
  printf( "waiting for sync (eNB_thread)\n" );
  pthread_mutex_lock( &sync_mutex );
1597

1598 1599
  while (sync_var<0)
    pthread_cond_wait( &sync_cond, &sync_mutex );
1600

1601
  pthread_mutex_unlock(&sync_mutex);
1602

1603
  int frame = 0;
1604

1605 1606
  while (!oai_exit) {
    start_meas( &softmodem_stats_mt );
Raymond Knopp's avatar
 
Raymond Knopp committed
1607

1608
#ifdef EXMIMO
1609 1610
    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]);
1611 1612
    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);
1613 1614 1615 1616
    //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];
1617

1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628
    //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;
1629

1630 1631
      if (diff<0)
        diff = diff +150;
1632

1633 1634 1635 1636
      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)))) {
1637

1638 1639 1640 1641
      // 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);
      
1642
      if (exit_missed_slots==1) {
1643 1644
        stop_meas(&softmodem_stats_mt);
        exit_fun("[HW][eNB] missed slot");
1645
      } else {
1646
        num_missed_slots++;
1647
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_MISSED_SLOTS_ENB,num_missed_slots );
1648
      }
1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670

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

    
1671
    }
1672

1673
    if (diff>8)
1674 1675
      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);
1676

1677 1678
    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);
1679 1680

    delay_cnt = 0;
1681

1682 1683 1684 1685
    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);
1686
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP,1);
1687
      ret = rt_sleep_ns(diff*DAQ_PERIOD);
1688 1689
      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);
1690

1691 1692
      if (ret)
        LOG_D(HW,"eNB Frame %d, time %llu: rt_sleep_ns returned %d\n",frame, time_in);
1693

Raymond Knopp's avatar
 
Raymond Knopp committed
1694
      hw_slot = (((((volatile unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15;
1695 1696 1697
      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());
1698
      delay_cnt++;
1699

1700 1701 1702 1703 1704
      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");
      }
1705

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1708
      if ((mbox_current>=135) && (mbox_target<15)) //handle the frame wrap-arround
1709
        diff = 150-mbox_current+mbox_target;
Raymond Knopp's avatar
 
Raymond Knopp committed
1710
      else if ((mbox_current<15) && (mbox_target>=135))
1711
        diff = -150+mbox_target-mbox_current;
Raymond Knopp's avatar
 
Raymond Knopp committed
1712
      else
1713 1714
        diff = mbox_target - mbox_current;
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1715

1716
#else  // EXMIMO
1717 1718
    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 );
1719
    tx_launched = 0;
1720

1721
    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
1722

1723
      unsigned int rxs;
Raymond Knopp's avatar
 
Raymond Knopp committed
1724
#ifndef USRP_DEBUG
1725 1726 1727
      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
1728

1729
      clock_gettime( CLOCK_MONOTONIC, &trx_time0 );
1730

1731 1732 1733
      // prepare rx buffer pointers
      for (int i=0; i<PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx; i++)
        rxp[i] = (void*)&rxdata[i][rx_pos];
1734

1735
      start_meas( &softmodem_stats_hw );
1736

1737
      openair0_timestamp timestamp;
1738 1739 1740 1741 1742 1743 1744
      rxs = openair0.trx_read_func(&openair0,
                                   &timestamp,
                                   rxp,
                                   spp,
                                   PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx);
      stop_meas( &softmodem_stats_hw );
      clock_gettime( CLOCK_MONOTONIC, &trx_time1 );
Raymond Knopp's avatar
 
Raymond Knopp committed
1745

1746 1747
      if (rxs != spp)
        exit_fun( "problem receiving samples" );
Raymond Knopp's avatar
 
Raymond Knopp committed
1748

1749
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
1750

1751
      // Transmit TX buffer based on timestamp from RX
1752
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763

      // prepare tx buffer pointers
      for (int i=0; i<PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx; i++)
        txp[i] = (void*)&txdata[i][tx_pos];

      if (frame > 50) {
        openair0.trx_write_func(&openair0,
                                (timestamp+(tx_delay*spp)-tx_forward_nsamps),
                                txp,
                                spp,
                                PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx,
1764
                                1);
Raymond Knopp's avatar
 
Raymond Knopp committed
1765 1766
      }

1767 1768
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, timestamp&0xffffffff );
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp+(tx_delay*spp)-tx_forward_nsamps)&0xffffffff );
1769 1770 1771 1772

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

1773
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE,0);
1774 1775 1776 1777 1778 1779 1780 1781
#else
      // USRP_DEBUG is active
      rt_sleep_ns(1000000);
#endif

      if ((tx_launched == 0) &&
          (rx_pos >= (((2*hw_subframe)+1)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))) {
        tx_launched = 1;
1782

1783
        for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818
          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;

      if (tx_pos >= samples_per_frame)
        tx_pos -= samples_per_frame;
    }

    if (rx_pos >= samples_per_frame)
      rx_pos -= samples_per_frame;

Raymond Knopp's avatar
 
Raymond Knopp committed
1819 1820

#endif // USRP
1821

1822
    if (oai_exit) break;
Raymond Knopp's avatar
 
Raymond Knopp committed
1823

1824 1825 1826 1827 1828
    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;
1829

1830 1831
      if (time_diff < timing_info.time_min)
        timing_info.time_min = time_diff;
1832

1833 1834
      if (time_diff > timing_info.time_max)
        timing_info.time_max = time_diff;
1835

1836 1837 1838 1839 1840 1841
      timing_info.time_avg += time_diff;
    }

    timing_info.n_samples++;

    if ((slot&1) == 1) {
1842
      // odd slot
1843
#ifdef EXMIMO
1844
      int sf = ((slot>>1)+1)%10;
Raymond Knopp's avatar
 
Raymond Knopp committed
1845
#else
1846
      int sf = hw_subframe;
Raymond Knopp's avatar
 
Raymond Knopp committed
1847
#endif
1848 1849

      for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1850 1851
#ifdef EXMIMO

1852 1853
        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);
1854 1855
        } 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);
1856 1857
          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);
1858

1859 1860 1861 1862
          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);
            }
1863
          } else {
1864 1865 1866 1867
            LOG_W(PHY,"[eNB] Frame %d, eNB TX thread %d busy!!\n",PHY_vars_eNB_g[0][CC_id]->proc[sf].frame_tx,sf);
            exit_fun("nothing to add");
          }
        }
1868

Raymond Knopp's avatar
 
Raymond Knopp committed
1869 1870
#endif

1871 1872 1873 1874 1875
        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;
        }
Raymond Knopp's avatar
 
Raymond Knopp committed
1876

1877
        int cnt_rx = ++PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_rx;
Raymond Knopp's avatar
 
Raymond Knopp committed
1878

1879
        pthread_mutex_unlock( &PHY_vars_eNB_g[0][CC_id]->proc[sf].mutex_rx );
Raymond Knopp's avatar
 
Raymond Knopp committed
1880

1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892
        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
1893
      }
1894 1895 1896 1897
    }

#ifdef EXMIMO
    slot++;
1898

1899 1900 1901 1902
    if (slot == 20) {
      frame++;
      slot = 0;
    }
1903

Raymond Knopp's avatar
 
Raymond Knopp committed
1904
#else
1905 1906
    hw_subframe++;
    slot += 2;
1907

1908
    if (hw_subframe == NUM_ENB_THREADS) {
1909
      // the radio frame is complete, start over
1910 1911 1912 1913
      hw_subframe = 0;
      frame++;
      slot = 1;
    }
1914 1915

#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1916

1917
#if defined(ENABLE_ITTI)
1918
    itti_update_lte_time( frame, slot );
1919
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1920
  }
1921 1922

eNB_thread_cleanup:
Raymond Knopp's avatar
 
Raymond Knopp committed
1923
#ifdef DEBUG_THREADS
1924
  printf( "eNB_thread: finished, ran %d times.\n", frame );
Raymond Knopp's avatar
 
Raymond Knopp committed
1925
#endif
1926

1927
#ifdef HARD_RT
Raymond Knopp's avatar
 
Raymond Knopp committed
1928
  rt_make_soft_real_time();
1929 1930
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
1931
#ifdef DEBUG_THREADS
1932
  printf( "Exiting eNB_thread ..." );
Raymond Knopp's avatar
 
Raymond Knopp committed
1933 1934
#endif
  // clean task
1935
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
1936
  rt_task_delete(task);
1937
#endif
1938 1939 1940

  eNB_thread_status = 0;
  return &eNB_thread_status;
Raymond Knopp's avatar
 
Raymond Knopp committed
1941
}
1942

1943

Raymond Knopp's avatar
 
Raymond Knopp committed
1944

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1945

1946 1947
static void get_options (int argc, char **argv)
{
1948 1949 1950
  int c;
  //  char                          line[1000];
  //  int                           l;
1951
  int k,i;//,j,k;
1952
#if defined(OAI_USRP) || defined(CPRIGW)
1953
  int clock_src;
1954
#endif
1955 1956 1957 1958 1959
  int CC_id;
#ifdef EXMIMO
  char rxg_fname[256], line[1000];
  FILE *rxg_fd;
  int l;
1960
#endif
1961 1962 1963



1964 1965

  const Enb_properties_array_t *enb_properties;
1966

1967 1968 1969 1970 1971 1972 1973
  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,
1974
    LONG_OPTION_NO_L2_CONNECT,
Raymond Knopp's avatar
 
Raymond Knopp committed
1975
    LONG_OPTION_CALIB_PRACH_TX,
1976 1977
    LONG_OPTION_RXGAIN,
    LONG_OPTION_TXGAIN,
1978
    LONG_OPTION_SCANCARRIER
1979
  };
1980

1981 1982 1983 1984 1985 1986 1987
  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
1988 1989 1990 1991
    {"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},
1992 1993 1994
    {NULL, 0, NULL, 0}
  };

1995
  while ((c = getopt_long (argc, argv, "C:dK:g:F:G:hqO:m:SUVRM:r:P:Ws:t:x:",long_options,NULL)) != -1) {
1996 1997 1998 1999 2000
    switch (c) {
    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;
2001

2002 2003 2004 2005 2006
    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;
2007

2008 2009 2010 2011
    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
2012
      break;
2013

2014 2015 2016 2017 2018
    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;
2019

2020 2021 2022
    case LONG_OPTION_DEBUG_UE_PRACH:
      mode = debug_prach;
      break;
2023

2024 2025 2026
    case LONG_OPTION_NO_L2_CONNECT:
      mode = no_L2_connect;
      break;
2027

Raymond Knopp's avatar
 
Raymond Knopp committed
2028 2029 2030 2031
    case LONG_OPTION_CALIB_PRACH_TX:
      mode = calib_prach_tx;
      break;

2032
    case LONG_OPTION_RXGAIN:
2033 2034
      for (i=0; i<4; i++)
        rx_gain[0][i] = atof(optarg);
2035

2036
      break;
2037

2038 2039 2040
    case LONG_OPTION_TXGAIN:
      for (i=0; i<4; i++)
        tx_gain[0][i] = atof(optarg);
2041

2042
      break;
2043

2044 2045 2046 2047 2048
    case LONG_OPTION_SCANCARRIER:
      UE_scan_carrier=1;

      break;

2049 2050 2051
    case 'M':
#ifdef ETHERNET
      strcpy(rrh_eNB_ip,optarg);
2052
#endif
2053
      break;
2054

2055
    case 'C':
2056 2057 2058 2059 2060 2061
      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]);
2062
      }
2063

2064
      UE_scan=0;
2065

2066
      break;
2067

2068 2069 2070 2071
    case 'd':
#ifdef XFORMS
      do_forms=1;
      printf("Running with XFORMS!\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2072
#endif
2073
      break;
2074

2075 2076 2077
    case 'K':
#if defined(ENABLE_ITTI)
      itti_dump_file = strdup(optarg);
2078
#else
2079
      printf("-K option is disabled when ENABLE_ITTI is not defined\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2080
#endif
2081
      break;
2082

2083 2084 2085
    case 'O':
      conf_config_file_name = optarg;
      break;
2086

2087 2088 2089
    case 'U':
      UE_flag = 1;
      break;
2090

2091 2092 2093
    case 'm':
      target_dl_mcs = atoi (optarg);
      break;
2094

2095 2096 2097
    case 't':
      target_ul_mcs = atoi (optarg);
      break;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2098
#ifdef OPENAIR2
2099

2100 2101 2102 2103 2104 2105 2106
    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");
      /*
2107 2108 2109
      if (optarg == NULL){
      in_ip[0] =NULL;
      printf("Enabling OPT for wireshark for local interface");
2110
      } else {
2111 2112 2113
      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);
2114 2115 2116
      }
      */
      break;
2117

2118
    case 'P':
2119 2120
      opt_type = OPT_PCAP;
      opt_enabled=1;
2121 2122 2123 2124 2125

      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");
2126
      } else {
2127 2128 2129
        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);
2130
      }
2131 2132

      break;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2133
#endif
2134

Raymond Knopp's avatar
 
Raymond Knopp committed
2135 2136 2137
    case 'V':
      ouput_vcd = 1;
      break;
2138

Raymond Knopp's avatar
 
Raymond Knopp committed
2139
    case  'q':
Raymond Knopp's avatar
 
Raymond Knopp committed
2140 2141
      opp_enabled = 1;
      break;
2142

Raymond Knopp's avatar
 
Raymond Knopp committed
2143 2144 2145
    case  'R' :
      online_log_messages =1;
      break;
2146

Raymond Knopp's avatar
 
Raymond Knopp committed
2147
    case 'r':
2148
      UE_scan = 0;
2149

2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175
      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
2176
      }
2177

2178
      break;
2179

Raymond Knopp's avatar
 
Raymond Knopp committed
2180
    case 's':
2181
#if defined(OAI_USRP) || defined(CPRIGW)
Raymond Knopp's avatar
 
Raymond Knopp committed
2182 2183

      clock_src = atoi(optarg);
2184

Raymond Knopp's avatar
 
Raymond Knopp committed
2185
      if (clock_src == 0) {
2186 2187 2188 2189 2190
        //  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
2191
      }
2192

Raymond Knopp's avatar
 
Raymond Knopp committed
2193 2194 2195 2196
#else
      printf("Note: -s not defined for ExpressMIMO2\n");
#endif
      break;
2197

2198 2199 2200 2201
    case 'S':
      exit_missed_slots=0;
      printf("Skip exit for missed slots\n");
      break;
2202

2203
    case 'g':
Raymond Knopp's avatar
 
Raymond Knopp committed
2204
      glog_level=atoi(optarg); // value between 1 - 9
2205
      break;
2206 2207

    case 'F':
2208
#ifdef EXMIMO
2209 2210
      sprintf(rxg_fname,"%srxg.lime",optarg);
      rxg_fd = fopen(rxg_fname,"r");
2211

2212
      if (rxg_fd) {
2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230
        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);

2231
#endif
2232
      break;
2233

2234 2235 2236
    case 'G':
      glog_verbosity=atoi(optarg);// value from 0, 0x5, 0x15, 0x35, 0x75
      break;
2237

2238 2239
    case 'x':
      transmission_mode = atoi(optarg);
2240

2241
      if (transmission_mode > 2) {
2242 2243
        printf("Transmission mode > 2 (%d) not supported for the moment\n",transmission_mode);
        exit(-1);
2244
      }
2245

2246
      break;
2247 2248 2249 2250
    case 'h':
      help ();
      exit (-1);
       
Raymond Knopp's avatar
 
Raymond Knopp committed
2251
    default:
2252 2253
      help ();
      exit (-1);
Raymond Knopp's avatar
 
Raymond Knopp committed
2254
      break;
2255 2256
    }
  }
2257

Raymond Knopp's avatar
 
Raymond Knopp committed
2258 2259
  if (UE_flag == 0)
    AssertFatal(conf_config_file_name != NULL,"Please provide a configuration file\n");
2260 2261


Raymond Knopp's avatar
 
Raymond Knopp committed
2262
  if ((UE_flag == 0) && (conf_config_file_name != NULL)) {
2263
    int i,j;
2264

Raymond Knopp's avatar
 
Raymond Knopp committed
2265
    NB_eNB_INST = 1;
2266

Raymond Knopp's avatar
 
Raymond Knopp committed
2267 2268
    /* Read eNB configuration file */
    enb_properties = enb_config_init(conf_config_file_name);
2269

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

Raymond Knopp's avatar
 
Raymond Knopp committed
2274
    /* Update some simulation parameters */
2275
    for (i=0; i < enb_properties->number; i++) {
2276
      AssertFatal (MAX_NUM_CCs == enb_properties->properties[i]->nb_cc,
2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293
                   "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
2294 2295
      }

2296

2297
#ifdef OPENAIR2
2298

2299 2300 2301
      init_all_otg(0);
      g_otg->seed = 0;
      init_seeds(g_otg->seed);
2302 2303 2304 2305 2306 2307 2308 2309 2310 2311

      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");
2312
      }
2313

2314
      init_predef_traffic(enb_properties->properties[i]->num_otg_elements, 1);
2315

2316
#endif
2317

2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331
      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
2332 2333 2334 2335 2336 2337
# 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
2338 2339 2340
#if defined (ENABLE_SECURITY)
      osa_log_level                  = enb_properties->properties[i]->osa_log_level;
      osa_log_verbosity              = enb_properties->properties[i]->osa_log_verbosity;
2341
#endif
Florian Kaltenberger's avatar
Florian Kaltenberger committed
2342

Raymond Knopp's avatar
 
Raymond Knopp committed
2343
      // adjust the log
2344
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
2345 2346 2347 2348 2349 2350 2351 2352 2353 2354
        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
2355
      } // CC_id
2356
    }// i
2357
  } else if ((UE_flag == 1) && (conf_config_file_name != NULL)) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2358 2359 2360 2361 2362 2363

    // 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
2364
}
2365

2366 2367
int main( int argc, char **argv )
{
Raymond Knopp's avatar
 
Raymond Knopp committed
2368
  int i,aa,card;
Lionel Gauthier's avatar
Lionel Gauthier committed
2369
#if defined (XFORMS) || defined (EMOS) || defined (EXMIMO)
Raymond Knopp's avatar
 
Raymond Knopp committed
2370
  void *status;
2371
#endif
2372

Raymond Knopp's avatar
 
Raymond Knopp committed
2373
  int CC_id;
Raymond Knopp's avatar
 
Raymond Knopp committed
2374
  uint16_t Nid_cell = 0;
2375
  uint8_t  cooperation_flag=0,  abstraction_flag=0;
2376
#ifndef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
2377
  uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2;
2378 2379 2380
#endif

#ifdef ENABLE_TCXO
Raymond Knopp's avatar
 
Raymond Knopp committed
2381
  unsigned int tcxo = 114;
2382 2383
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
2384
#if defined (XFORMS)
2385 2386
  int ret;
#endif
2387
#if defined (EMOS) || (! defined (RTAI))
Raymond Knopp's avatar
 
Raymond Knopp committed
2388
  int error_code;
2389
#endif
2390

2391 2392 2393 2394 2395
#ifdef DEBUG_CONSOLE
  setvbuf(stdout, NULL, _IONBF, 0);
  setvbuf(stderr, NULL, _IONBF, 0);
#endif

2396 2397 2398
  PHY_VARS_UE *UE[MAX_NUM_CCs];

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

2401
  memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
Raymond Knopp's avatar
 
Raymond Knopp committed
2402
  set_latency_target();
2403

2404

2405

2406
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2407 2408
    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 */
2409
    frame_parms[CC_id]->frame_type         = FDD; /* TDD */
Raymond Knopp's avatar
 
Raymond Knopp committed
2410 2411
    frame_parms[CC_id]->tdd_config          = 3;
    frame_parms[CC_id]->tdd_config_S        = 0;
2412 2413
    frame_parms[CC_id]->N_RB_DL             = 100;
    frame_parms[CC_id]->N_RB_UL             = 100;
Raymond Knopp's avatar
 
Raymond Knopp committed
2414
    frame_parms[CC_id]->Ncp                 = NORMAL;
Raymond Knopp's avatar
 
Raymond Knopp committed
2415 2416
    frame_parms[CC_id]->Ncp_UL              = NORMAL;
    frame_parms[CC_id]->Nid_cell            = Nid_cell;
Raymond Knopp's avatar
 
Raymond Knopp committed
2417
    frame_parms[CC_id]->num_MBSFN_config    = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2418 2419 2420
    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
2421
  }
2422

2423 2424 2425 2426 2427
  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];
2428
    //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
2429
  }
2430 2431
  logInit();
 
2432
  get_options (argc, argv); //Command-line options
2433 2434 2435 2436 2437
 
  // initialize mscgen log
  MSC_INIT(MSC_E_UTRAN);
  
  // initialize the log (see log.h for details)
Florian Kaltenberger's avatar
Florian Kaltenberger committed
2438 2439
  set_glog(glog_level, glog_verbosity);

2440 2441
  //randominit (0);
  set_taus_seed (0);
Raymond Knopp's avatar
 
Raymond Knopp committed
2442

2443 2444
  if (UE_flag==1) {
    printf("configuring for UE\n");
2445

2446
    set_comp_log(HW,      LOG_DEBUG,  LOG_HIGH, 1);
2447
#ifdef OPENAIR2
2448
    set_comp_log(PHY,     LOG_DEBUG,   LOG_HIGH, 1);
2449
#else
2450
    set_comp_log(PHY,     LOG_INFO,   LOG_HIGH, 1);
2451
#endif
2452 2453 2454 2455 2456
    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);
2457
#if defined(ENABLE_ITTI)
2458
    set_comp_log(EMU,     LOG_INFO,   LOG_MED, 1);
2459
# if defined(ENABLE_USE_MME)
2460
    set_comp_log(NAS,     LOG_INFO,   LOG_HIGH, 1);
2461 2462
# endif
#endif
2463 2464
  } else {
    printf("configuring for eNB\n");
2465

2466
    set_comp_log(HW,      hw_log_level, hw_log_verbosity, 1);
2467
#ifdef OPENAIR2
2468 2469 2470 2471 2472
    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);

2473
#else
2474
    set_comp_log(PHY,     LOG_INFO,   LOG_HIGH, 1);
2475
#endif
2476 2477 2478 2479
    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);
2480
#if defined(ENABLE_ITTI)
2481
    set_comp_log(EMU,     LOG_INFO,   LOG_MED, 1);
2482
# if defined(ENABLE_USE_MME)
2483 2484 2485 2486
    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);
2487
# endif
2488
#if defined(ENABLE_SECURITY)
2489
    set_comp_log(OSA,    osa_log_level,   osa_log_verbosity, 1);
2490
#endif
2491
#endif
2492
#ifdef LOCALIZATION
2493 2494 2495 2496 2497 2498 2499 2500 2501
    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
2502
    }
2503
  }
2504

Raymond Knopp's avatar
 
Raymond Knopp committed
2505 2506
  if (ouput_vcd) {
    if (UE_flag==1)
2507
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_UE.vcd");
Raymond Knopp's avatar
 
Raymond Knopp committed
2508
    else
2509
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_eNB.vcd");
Raymond Knopp's avatar
 
Raymond Knopp committed
2510
  }
2511

2512 2513
  if (opp_enabled ==1)
    reset_opp_meas();
2514

2515
#if defined(ENABLE_ITTI)
2516

Raymond Knopp's avatar
 
Raymond Knopp committed
2517 2518
  if (UE_flag == 1) {
    log_set_instance_type (LOG_INSTANCE_UE);
2519
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
2520 2521
    log_set_instance_type (LOG_INSTANCE_ENB);
  }
2522

Raymond Knopp's avatar
 
Raymond Knopp committed
2523
  itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, itti_dump_file);
2524
#endif
2525
#ifdef OPENAIR2
2526

2527 2528
  if (opt_type != OPT_NONE) {
    radio_type_t radio_type;
2529

2530 2531
    if (frame_parms[0]->frame_type == FDD)
      radio_type = RADIO_TYPE_FDD;
2532
    else
2533
      radio_type = RADIO_TYPE_TDD;
2534

2535 2536 2537
    if (init_opt(in_path, in_ip, NULL, radio_type) == -1)
      LOG_E(OPT,"failed to run OPT \n");
  }
2538

2539
#endif
2540
#ifdef NAS_NETLINK
Raymond Knopp's avatar
 
Raymond Knopp committed
2541
  netlink_init();
2542 2543
#endif

2544
#if !defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
2545 2546 2547
  // to make a graceful exit when ctrl-c is pressed
  signal(SIGSEGV, signal_handler);
  signal(SIGINT, signal_handler);
2548
#endif
2549 2550

#ifndef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
2551 2552 2553 2554
  check_clock();
#endif

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

2558 2559 2560 2561 2562 2563 2564 2565 2566
    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
2567 2568 2569 2570 2571 2572 2573 2574
    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;
2575 2576
    init_ul_hopping(frame_parms[CC_id]);
    init_frame_parms(frame_parms[CC_id],1);
2577 2578
    //   phy_init_top(frame_parms[CC_id]);
    phy_init_lte_top(frame_parms[CC_id]);
Raymond Knopp's avatar
 
Raymond Knopp committed
2579 2580 2581
  }


2582
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2583
    //init prach for openair1 test
2584
    frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22;
Raymond Knopp's avatar
 
Raymond Knopp committed
2585
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1;
2586
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2587 2588 2589
    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
2590
    // N_ZC = (prach_fmt <4)?839:139;
Raymond Knopp's avatar
 
Raymond Knopp committed
2591
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
2592 2593

  if (UE_flag==1) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2594 2595 2596
    NB_UE_INST=1;
    NB_INST=1;

Raymond Knopp's avatar
 
Raymond Knopp committed
2597 2598
    PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE**));
    PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_UE*)*MAX_NUM_CCs);
2599 2600

    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
2601 2602 2603 2604

      PHY_vars_UE_g[0][CC_id] = init_lte_UE(frame_parms[CC_id], 0,abstraction_flag,transmission_mode);
      UE[CC_id] = PHY_vars_UE_g[0][CC_id];
      printf("PHY_vars_UE_g[0][%d] = %p\n",CC_id,UE[CC_id]);
Raymond Knopp's avatar
 
Raymond Knopp committed
2605
#ifndef OPENAIR2
2606 2607 2608 2609 2610 2611 2612 2613 2614

      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
2615
      }
2616

2617
#endif
2618 2619 2620


      UE[CC_id]->UE_scan = UE_scan;
2621
      UE[CC_id]->UE_scan_carrier = UE_scan_carrier;
2622 2623 2624
      UE[CC_id]->mode    = mode;

      compute_prach_seq(&UE[CC_id]->lte_frame_parms.prach_config_common,
2625 2626 2627
                        UE[CC_id]->lte_frame_parms.frame_type,
                        UE[CC_id]->X_u);

2628
      UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1234;
2629
#ifndef OPENAIR2
2630
      UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1235;
2631
#endif
2632

2633
#ifdef EXMIMO
2634

2635 2636 2637 2638
      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
2639
      }
2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658

      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
2659
      }
2660

2661
#else
2662
      UE[CC_id]->rx_total_gain_dB =  (int)rx_gain[CC_id][0];
2663
#endif
2664

2665
      UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id];
2666

2667 2668


2669
#ifdef EXMIMO
2670

Raymond Knopp's avatar
 
Raymond Knopp committed
2671
      //N_TA_offset
2672
      if (UE[CC_id]->lte_frame_parms.frame_type == TDD) {
2673 2674 2675 2676 2677 2678 2679 2680
        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
2681
      }
2682

2683
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
2684
      //already taken care of in lte-softmodem
2685
      UE[CC_id]->N_TA_offset = 0;
2686
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2687
    }
2688

Raymond Knopp's avatar
 
Raymond Knopp committed
2689 2690 2691 2692
    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;
2693 2694 2695



Raymond Knopp's avatar
 
Raymond Knopp committed
2696
    //  printf("tx_max_power = %d -> amp %d\n",tx_max_power,get_tx_amp(tx_max_power,tx_max_power));
2697 2698 2699 2700 2701 2702 2703 2704 2705
  } 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++) {
      PHY_vars_eNB_g[0][CC_id] = init_lte_eNB(frame_parms[CC_id],0,Nid_cell,cooperation_flag,transmission_mode,abstraction_flag);
      PHY_vars_eNB_g[0][CC_id]->CC_id = CC_id;

2706
#ifndef OPENAIR2
2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722

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

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

#endif

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

2724
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
2725

2726
      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
2727

2728
#else
2729 2730 2731
      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
2732

2733 2734 2735
      // 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
2736

2737
#endif
2738

2739
#ifdef EXMIMO
2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750

      //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
2751
      }
2752

2753 2754 2755 2756
#else
      //already taken care of in lte-softmodem
      PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 0;
#endif
2757

2758
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
2759 2760


2761 2762 2763 2764 2765 2766 2767 2768 2769
    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;

  }
2770

2771

2772

Raymond Knopp's avatar
 
Raymond Knopp committed
2773
  dump_frame_parms(frame_parms[0]);
2774

Raymond Knopp's avatar
 
Raymond Knopp committed
2775
  if(frame_parms[0]->N_RB_DL == 100) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2776
    sample_rate = 30.72e6;
2777
#ifndef EXMIMO
2778
    openair0_cfg[0].samples_per_packet = 2048;
Raymond Knopp's avatar
 
Raymond Knopp committed
2779 2780 2781
    samples_per_frame = 307200;
    // from usrp_time_offset
    tx_forward_nsamps = 175;
2782
    tx_delay = 8;
Raymond Knopp's avatar
 
Raymond Knopp committed
2783
#endif
2784
  } else if(frame_parms[0]->N_RB_DL == 50) {
2785
    sample_rate = 15.36e6;
2786
#ifndef EXMIMO
2787
    openair0_cfg[0].samples_per_packet = 2048;
Raymond Knopp's avatar
 
Raymond Knopp committed
2788 2789
    samples_per_frame = 153600;
    tx_forward_nsamps = 95;
2790
    tx_delay = 5;
Raymond Knopp's avatar
 
Raymond Knopp committed
2791
#endif
2792
  } else if (frame_parms[0]->N_RB_DL == 25) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2793
    sample_rate = 7.68e6;
2794
#ifndef EXMIMO
2795
    openair0_cfg[0].samples_per_packet = 1024;
Raymond Knopp's avatar
 
Raymond Knopp committed
2796 2797
    samples_per_frame = 76800;
    tx_forward_nsamps = 70;
2798
    tx_delay = 6;
Raymond Knopp's avatar
 
Raymond Knopp committed
2799
#endif
2800
  } else if (frame_parms[0]->N_RB_DL == 6) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2801 2802
    sample_rate = 1.92e6;
#ifndef EXMIMO
2803
    openair0_cfg[0].samples_per_packet = 256;
Raymond Knopp's avatar
 
Raymond Knopp committed
2804 2805
    samples_per_frame = 19200;
    tx_forward_nsamps = 40;
2806
    tx_delay = 8;
Raymond Knopp's avatar
 
Raymond Knopp committed
2807 2808
#endif
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
2809 2810

#ifdef ETHERNET
2811

thomasl's avatar
thomasl committed
2812
  if (frame_parms[0]->N_RB_DL == 6) openair0_cfg[0].samples_per_packet = 256;
2813
  else openair0_cfg[0].samples_per_packet = 1536;
Raymond Knopp's avatar
 
Raymond Knopp committed
2814

2815
  printf("HW: samples_per_packet %d\n",openair0_cfg[0].samples_per_packet);
Raymond Knopp's avatar
 
Raymond Knopp committed
2816 2817
#endif

2818

2819
  for (card=0; card<MAX_CARDS; card++) {
2820
#ifndef EXMIMO
2821
    openair0_cfg[card].samples_per_packet = openair0_cfg[0].samples_per_packet;
2822 2823
#endif
    printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card,
2824 2825
           ((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
2826 2827
    openair0_cfg[card].Mod_id = 0;
#ifdef ETHERNET
2828 2829

    if (UE_flag) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2830 2831 2832
      printf("ETHERNET: Configuring UE ETH for %s:%d\n",rrh_UE_ip,rrh_UE_port);
      openair0_cfg[card].rrh_ip   = &rrh_UE_ip[0];
      openair0_cfg[card].rrh_port = rrh_UE_port;
2833 2834 2835 2836
    } else {
      printf("ETHERNET: Configuring eNB ETH for %s:%d\n",rrh_eNB_ip,rrh_eNB_port);
      openair0_cfg[card].rrh_ip   = &rrh_eNB_ip[0];
      openair0_cfg[card].rrh_port = rrh_eNB_port;
ghaddab's avatar
ghaddab committed
2837
    }
2838

Raymond Knopp's avatar
 
Raymond Knopp committed
2839
#endif
2840 2841 2842
    openair0_cfg[card].sample_rate = sample_rate;
    openair0_cfg[card].tx_bw = bw;
    openair0_cfg[card].rx_bw = bw;
2843
    // in the case of the USRP, the following variables need to be initialized before the init
2844
    // since the USRP only supports one CC (for the moment), we initialize all the cards with first CC.
2845
    // in the case of EXMIMO2, these values are overwirtten in the function setup_eNB/UE_buffer
2846
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
2847 2848
    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));
2849 2850

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

2852
      openair0_cfg[card].autocal[i] = 1;
2853
      openair0_cfg[card].tx_gain[i] = tx_gain[0][i];
2854
      openair0_cfg[card].rx_gain[i] = ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->rx_total_gain_eNB_dB :
2855
                                       PHY_vars_UE_g[0][0]->rx_total_gain_dB) - USRP_GAIN_OFFSET;  // calibrated for USRP B210 @ 2.6 GHz, 30.72 MS/s
2856

2857 2858
      switch(frame_parms[0]->N_RB_DL) {
      case 6:
2859 2860 2861
        openair0_cfg[card].rx_gain[i] -= 6;
        break;

2862
      case 25:
2863 2864 2865
        openair0_cfg[card].rx_gain[i] += 6;
        break;

2866
      case 50:
2867 2868 2869
        openair0_cfg[card].rx_gain[i] += 8;
        break;

2870
      default:
2871
        break;
2872
      }
2873

2874 2875
      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];
2876
      printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n",
2877 2878 2879 2880 2881
             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]);

Raymond Knopp's avatar
 
Raymond Knopp committed
2882
    }
2883

2884
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2885
  }
2886

2887
  printf("Initializing openair0 ...");
2888
  openair0_cfg[0].log_level = glog_level;
2889

2890
  if (openair0_device_init(&openair0, &openair0_cfg[0]) <0) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2891 2892 2893
    printf("Exiting, cannot initialize device\n");
    exit(-1);
  }
2894

2895
  printf("Done\n");
2896 2897 2898

  mac_xface = malloc(sizeof(MAC_xface));

2899
#ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
2900
  int eMBMS_active=0;
2901

Raymond Knopp's avatar
 
Raymond Knopp committed
2902
  l2_init(frame_parms[0],eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL,
2903 2904 2905 2906
          0,// cba_group_active
          0); // HO flag


2907 2908
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
2909
  mac_xface->macphy_exit = &exit_fun;
2910

winckel's avatar
winckel committed
2911
#if defined(ENABLE_ITTI)
2912

Raymond Knopp's avatar
 
Raymond Knopp committed
2913
  if (create_tasks(UE_flag ? 0 : 1, UE_flag ? 1 : 0) < 0) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
2914
    printf("cannot create ITTI tasks\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2915 2916
    exit(-1); // need a softer mode
  }
2917

Raymond Knopp's avatar
 
Raymond Knopp committed
2918
  printf("ITTI tasks created\n");
winckel's avatar
winckel committed
2919
#endif
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2920 2921

#ifdef OPENAIR2
2922
  if (UE_flag==1) {
2923
    printf("Filling UE band info\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2924
    fill_ue_band_info();
2925
    mac_xface->dl_phy_sync_success (0, 0, 0, 1);
2926
  } else
2927
    mac_xface->mrbch_phy_sync_failure (0, 0, 0);
2928

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2929
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2930

2931
  /* #ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
2932 2933 2934 2935 2936 2937
  //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
2938 2939 2940 2941 2942 2943
  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
2944 2945 2946
  }
  init_predef_traffic(UE_flag ? 1 : 0, UE_flag ? 0 : 1);
  //  }
2947
  #endif */
Raymond Knopp's avatar
 
Raymond Knopp committed
2948

2949
#ifdef EXMIMO
2950
  number_of_cards = openair0_num_detected_cards;
2951 2952
#else
  number_of_cards = 1;
2953
#endif
2954

2955

2956

2957
  for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
2958
    rf_map[CC_id].card=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2959
    rf_map[CC_id].chain=CC_id;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
2960
  }
2961

Raymond Knopp's avatar
 
Raymond Knopp committed
2962 2963
  // connect the TX/RX buffers
  if (UE_flag==1) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2964
    openair_daq_vars.timing_advance = 0;
2965

2966
    if (setup_ue_buffers(UE,&openair0_cfg[0],rf_map)!=0) {
2967 2968 2969
      printf("Error setting up eNB buffer\n");
      exit(-1);
    }
2970

2971
    printf("Setting UE buffer to all-RX\n");
2972

2973
    // Set LSBs for antenna switch (ExpressMIMO)
2974
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2975
      for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++)
2976 2977
        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
2978
    }
2979

Raymond Knopp's avatar
 
Raymond Knopp committed
2980
    //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX;
2981
  } else {
2982
    openair_daq_vars.timing_advance = 0;
2983

2984 2985 2986 2987
    if (setup_eNB_buffers(PHY_vars_eNB_g[0],&openair0_cfg[0],rf_map)!=0) {
      printf("Error setting up eNB buffer\n");
      exit(-1);
    }
2988

2989
    printf("Setting eNB buffer to all-RX\n");
2990

2991
    // Set LSBs for antenna switch (ExpressMIMO)
2992
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2993
      for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++)
2994 2995
        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
2996
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
2997
  }
2998

2999
#ifdef EXMIMO
3000
  openair0_config(&openair0_cfg[0],UE_flag);
Raymond Knopp's avatar
 
Raymond Knopp committed
3001 3002
#endif

3003
  /*
Raymond Knopp's avatar
 
Raymond Knopp committed
3004 3005
      for (ant=0;ant<4;ant++)
      p_exmimo_config->rf.do_autocal[ant] = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3006
  */
3007 3008

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3011 3012 3013 3014 3015 3016
  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);
3017
  else
Raymond Knopp's avatar
 
Raymond Knopp committed
3018
    printf("[OPENAIR][SCHED][INIT] Problem creating EMOS FIFO %d, error_code %d\n",CHANSOUNDER_FIFO_MINOR,error_code);
3019

3020 3021
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3022
  mlockall(MCL_CURRENT | MCL_FUTURE);
3023 3024

#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3025
  // make main thread LXRT soft realtime
3026
  /* task = */ rt_task_init_schmod(nam2num("MAIN"), 9, 0, 0, SCHED_FIFO, 0xF);
Raymond Knopp's avatar
 
Raymond Knopp committed
3027 3028 3029 3030 3031

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3034 3035
  pthread_cond_init(&sync_cond,NULL);
  pthread_mutex_init(&sync_mutex, NULL);
3036

3037
#if defined(ENABLE_ITTI)
3038

Florian Kaltenberger's avatar
Florian Kaltenberger committed
3039 3040 3041 3042 3043
  // Wait for eNB application initialization to be complete (eNB registration to MME)
  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);
  }
3044

3045
#endif
3046

Raymond Knopp's avatar
 
Raymond Knopp committed
3047 3048

  // this starts the DMA transfers
3049
#ifdef EXMIMO
3050

Raymond Knopp's avatar
 
Raymond Knopp committed
3051
  if (UE_flag!=1)
3052
    for (card=0; card<openair0_num_detected_cards; card++)
3053
      openair0_start_rt_acquisition(card);
3054

Raymond Knopp's avatar
 
Raymond Knopp committed
3055
#endif
3056 3057

#ifdef XFORMS
3058 3059
  int UE_id;

Raymond Knopp's avatar
 
Raymond Knopp committed
3060 3061
  if (do_forms==1) {
    fl_initialize (&argc, argv, NULL, 0, 0);
3062 3063

    if (UE_flag==0) {
3064
      form_stats_l2 = create_form_stats_form();
3065 3066 3067
      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");
3068 3069

      for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082
	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");
	  }
	}
3083
      }
3084
    } else {
3085 3086 3087 3088 3089 3090 3091
      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
3092
      if (openair_daq_vars.use_ia_receiver) {
3093 3094 3095 3096 3097
        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
3098 3099 3100
      }
    }

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

3103 3104
    if (ret == 0)
      pthread_setname_np( forms_thread, "xforms" );
3105

Raymond Knopp's avatar
 
Raymond Knopp committed
3106 3107
    printf("Scope thread created, ret=%d\n",ret);
  }
3108

3109 3110 3111
#endif

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3112 3113
  ret = pthread_create(&thread3, NULL, emos_thread, NULL);
  printf("EMOS thread created, ret=%d\n",ret);
jiangx's avatar
jiangx committed
3114 3115
  ret = pthread_create(&thread4, NULL, gps_thread, NULL);
  printf("GPS thread created, ret=%d\n",ret);
3116 3117
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3118
  rt_sleep_ns(10*FRAME_PERIOD);
3119 3120

#ifndef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3121
  pthread_attr_init (&attr_dlsch_threads);
3122
  pthread_attr_setstacksize(&attr_dlsch_threads,4*PTHREAD_STACK_MIN);
3123

3124
  pthread_attr_init (&attr_UE_thread);
3125
  pthread_attr_setstacksize(&attr_UE_thread,8192);//5*PTHREAD_STACK_MIN);
3126

3127
#ifndef LOWLATENCY
3128 3129
  sched_param_UE_thread.sched_priority = sched_get_priority_max(SCHED_FIFO);
  pthread_attr_setschedparam(&attr_UE_thread,&sched_param_UE_thread);
3130
  sched_param_dlsch.sched_priority = sched_get_priority_max(SCHED_FIFO); //OPENAIR_THREAD_PRIORITY;
Raymond Knopp's avatar
 
Raymond Knopp committed
3131 3132
  pthread_attr_setschedparam  (&attr_dlsch_threads, &sched_param_dlsch);
  pthread_attr_setschedpolicy (&attr_dlsch_threads, SCHED_FIFO);
3133
  printf("Setting eNB_thread FIFO scheduling policy with priority %d \n", sched_param_dlsch.sched_priority);
3134
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3135

3136 3137
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3138 3139
  // start the main thread
  if (UE_flag == 1) {
3140
    printf("Intializing UE Threads ...\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3141
    init_UE_threads();
3142 3143 3144 3145 3146
#ifdef DLSCH_THREAD
    init_rx_pdsch_thread();
    rt_sleep_ns(FRAME_PERIOD/10);
    init_dlsch_threads();
#endif
3147

3148
    sleep(1);
3149
#ifdef RTAI
3150
    main_ue_thread = rt_thread_create(UE_thread, NULL, 100000000);
3151
#else
3152
    error_code = pthread_create(&main_ue_thread, &attr_UE_thread, UE_thread, NULL);
3153

Raymond Knopp's avatar
 
Raymond Knopp committed
3154 3155 3156
    if (error_code!= 0) {
      LOG_D(HW,"[lte-softmodem.c] Could not allocate UE_thread, error %d\n",error_code);
      return(error_code);
3157
    } else {
3158 3159
      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
3160
    }
3161

3162
#endif
3163
    printf("UE threads created\n");
3164
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
3165 3166
    if (multi_thread>0) {
      init_eNB_proc();
3167
      sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3168 3169
      LOG_D(HW,"[lte-softmodem.c] eNB threads created\n");
    }
3170

3171
    printf("Creating main eNB_thread \n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3172
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3173
    main_eNB_thread = rt_thread_create(eNB_thread, NULL, PTHREAD_STACK_MIN);
Raymond Knopp's avatar
 
Raymond Knopp committed
3174
#else
3175
    error_code = pthread_create( &main_eNB_thread, &attr_dlsch_threads, eNB_thread, NULL );
3176

Raymond Knopp's avatar
 
Raymond Knopp committed
3177 3178 3179
    if (error_code!= 0) {
      LOG_D(HW,"[lte-softmodem.c] Could not allocate eNB_thread, error %d\n",error_code);
      return(error_code);
3180
    } else {
3181 3182
      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
3183
    }
3184

Raymond Knopp's avatar
 
Raymond Knopp committed
3185 3186
#endif
  }
3187

Raymond Knopp's avatar
 
Raymond Knopp committed
3188
  // Sleep to allow all threads to setup
Raymond Knopp's avatar
 
Raymond Knopp committed
3189
  sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3190

3191
#ifdef USE_MME
3192

3193 3194 3195
  while (start_UE == 0) {
    sleep(1);
  }
3196

3197 3198
#endif

3199
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3200
#ifndef USRP_DEBUG
Raymond Knopp's avatar
 
Raymond Knopp committed
3201
  openair0.trx_start_func(&openair0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3202
  //  printf("returning from usrp start streaming: %llu\n",get_usrp_time(&openair0));
Raymond Knopp's avatar
 
Raymond Knopp committed
3203
#endif
3204 3205
#endif

3206

Raymond Knopp's avatar
 
Raymond Knopp committed
3207
  pthread_mutex_lock(&sync_mutex);
3208
  sync_var=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3209 3210
  pthread_cond_broadcast(&sync_cond);
  pthread_mutex_unlock(&sync_mutex);
3211

Raymond Knopp's avatar
 
Raymond Knopp committed
3212 3213 3214
  // wait for end of program
  printf("TYPE <CTRL-C> TO TERMINATE\n");
  //getchar();
3215 3216

#if defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
3217 3218
  printf("Entering ITTI signals handler\n");
  itti_wait_tasks_end();
3219
  oai_exit=1;
3220
#else
3221

Raymond Knopp's avatar
 
Raymond Knopp committed
3222 3223
  while (oai_exit==0)
    rt_sleep_ns(FRAME_PERIOD);
3224

3225
#endif
3226

Raymond Knopp's avatar
 
Raymond Knopp committed
3227
  // stop threads
3228
#ifdef XFORMS
Raymond Knopp's avatar
 
Raymond Knopp committed
3229
  printf("waiting for XFORMS thread\n");
3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243

  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++) {
3244 3245 3246 3247
	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
3248
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
3249
    }
3250 3251
  }

3252 3253
#endif

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3256 3257
  // cleanup
  if (UE_flag == 1) {
3258
#ifdef EXMIMO
3259
#ifdef RTAI
3260
    rt_thread_join(main_ue_thread);
3261
#else
3262
    pthread_join(main_ue_thread,&status);
3263 3264
#endif
#ifdef DLSCH_THREAD
Raymond Knopp's avatar
 
Raymond Knopp committed
3265 3266
    cleanup_dlsch_threads();
    cleanup_rx_pdsch_thread();
3267
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3268
#endif
3269
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
3270
#ifdef DEBUG_THREADS
Raymond Knopp's avatar
 
Raymond Knopp committed
3271
    printf("Joining eNB_thread ...");
Raymond Knopp's avatar
 
Raymond Knopp committed
3272
#endif
3273
#ifdef RTAI
3274
    rt_thread_join(main_eNB_thread);
3275
#else
3276 3277
    int *eNB_thread_status_p;
    int result = pthread_join( main_eNB_thread, (void**)&eNB_thread_status_p );
Raymond Knopp's avatar
 
Raymond Knopp committed
3278
#ifdef DEBUG_THREADS
3279

3280
    if (result != 0) {
3281
      printf( "\nError joining main_eNB_thread.\n" );
3282
    } else {
3283 3284 3285 3286 3287
      if (eNB_thread_status_p) {
        printf( "status %d\n", *eNB_thread_status_p );
      } else {
        printf( "The thread was killed. No status available.\n");
      }
3288
    }
3289

3290 3291
#else
    UNUSED(result);
3292 3293
#endif // DEBUG_THREADS
#endif // RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3294

Raymond Knopp's avatar
 
Raymond Knopp committed
3295 3296 3297
    if (multi_thread>0) {
      printf("Killing eNB processing threads\n");
      kill_eNB_proc();
Raymond Knopp's avatar
 
Raymond Knopp committed
3298

Raymond Knopp's avatar
 
Raymond Knopp committed
3299
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3300
  }
3301

3302
#ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
3303
  //cleanup_pdcp_thread();
3304 3305
#endif

3306
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3307
  stop_rt_timer();
3308
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3309 3310
  pthread_cond_destroy(&sync_cond);
  pthread_mutex_destroy(&sync_mutex);
3311

3312

3313
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3314
  printf("stopping card\n");
3315
  openair0_stop(0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3316 3317
  printf("closing openair0_lib\n");
  openair0_close();
Raymond Knopp's avatar
 
Raymond Knopp committed
3318
#endif
3319 3320

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3321 3322 3323
  printf("waiting for EMOS thread\n");
  pthread_cancel(thread3);
  pthread_join(thread3,&status);
jiangx's avatar
jiangx committed
3324 3325 3326
  printf("waiting for GPS thread\n");
  pthread_cancel(thread4);
  pthread_join(thread4,&status);
3327 3328 3329
#endif

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3330 3331
  error_code = rtf_destroy(CHANSOUNDER_FIFO_MINOR);
  printf("[OPENAIR][SCHED][CLEANUP] EMOS FIFO closed, error_code %d\n", error_code);
3332 3333
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3334
  if (ouput_vcd)
3335
    VCD_SIGNAL_DUMPER_CLOSE();
3336

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3337
#ifdef OPENAIR2
3338

3339
  if (opt_enabled == 1)
3340
    terminate_opt();
3341

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3342
#endif
3343

Raymond Knopp's avatar
 
Raymond Knopp committed
3344
  logClean();
3345

Raymond Knopp's avatar
 
Raymond Knopp committed
3346 3347
  return 0;
}
3348 3349


3350 3351 3352
/* 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
3353
   antennas are mapped to successive RF chains on the same card. */
3354 3355
int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs])
{
3356

3357
  int i, CC_id;
3358
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3359
  uint16_t N_TA_offset = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3360 3361
#else
  int j;
Raymond Knopp's avatar
 
Raymond Knopp committed
3362
#endif
3363
  LTE_DL_FRAME_PARMS *frame_parms;
3364

Raymond Knopp's avatar
 
Raymond Knopp committed
3365

3366 3367
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    if (phy_vars_eNB[CC_id]) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3368 3369
      frame_parms = &(phy_vars_eNB[CC_id]->lte_frame_parms);
      printf("setup_eNB_buffers: frame_parms = %p\n",frame_parms);
3370
    } else {
3371 3372
      printf("phy_vars_eNB[%d] not initialized\n", CC_id);
      return(-1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3373
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3374

3375
#ifndef EXMIMO
3376

3377 3378
    if (frame_parms->frame_type == TDD) {
      if (frame_parms->N_RB_DL == 100)
3379
        N_TA_offset = 624;
3380
      else if (frame_parms->N_RB_DL == 50)
3381
        N_TA_offset = 624/2;
3382
      else if (frame_parms->N_RB_DL == 25)
3383
        N_TA_offset = 624/4;
Raymond Knopp's avatar
 
Raymond Knopp committed
3384
    }
3385

Raymond Knopp's avatar
 
Raymond Knopp committed
3386
#endif
3387 3388


3389 3390 3391



Raymond Knopp's avatar
 
Raymond Knopp committed
3392
    // replace RX signal buffers with mmaped HW versions
3393
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3394 3395 3396
    openair0_cfg[CC_id].tx_num_channels = 0;
    openair0_cfg[CC_id].rx_num_channels = 0;

3397
    for (i=0; i<frame_parms->nb_antennas_rx; i++) {
3398 3399 3400
      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];
3401

3402
      if (openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i]) {
3403 3404 3405 3406 3407 3408
        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++;
3409
      }
3410

3411
      printf("rxdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]);
3412 3413 3414 3415

      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;
3416
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
3417
    }
3418 3419

    for (i=0; i<frame_parms->nb_antennas_tx; i++) {
3420 3421 3422
      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];
3423

3424
      if (openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i]) {
3425 3426 3427 3428 3429 3430
        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++;
3431
      }
3432

3433
      printf("txdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3434 3435 3436 3437

      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;
3438
      }
3439
    }
3440

3441
#else // not EXMIMO
3442 3443 3444
    rxdata = (int32_t**)malloc16(frame_parms->nb_antennas_rx*sizeof(int32_t*));
    txdata = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*));

3445
    for (i=0; i<frame_parms->nb_antennas_rx; i++) {
3446
      free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]);
3447 3448
      rxdata[i] = (int32_t*)(16 + malloc16(16+samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation
      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
3449 3450
      memset(rxdata[i], 0, samples_per_frame*sizeof(int32_t));
      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);
Raymond Knopp's avatar
 
Raymond Knopp committed
3451
    }
3452 3453

    for (i=0; i<frame_parms->nb_antennas_tx; i++) {
3454
      free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3455
      txdata[i] = (int32_t*)(16 + malloc16(16 + samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation
3456 3457
      phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i] = txdata[i];
      memset(txdata[i], 0, samples_per_frame*sizeof(int32_t));
3458
      printf("txdata[%d] @ %p\n", i, phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3459

Raymond Knopp's avatar
 
Raymond Knopp committed
3460
    }
3461

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

3465
  return(0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3466
}
3467

3468 3469
void reset_opp_meas(void)
{
3470 3471 3472
  int sfn;
  reset_meas(&softmodem_stats_mt);
  reset_meas(&softmodem_stats_hw);
3473

3474 3475 3476 3477 3478 3479
  for (sfn=0; sfn < 10; sfn++) {
    reset_meas(&softmodem_stats_tx_sf[sfn]);
    reset_meas(&softmodem_stats_rx_sf[sfn]);
  }
}

3480 3481
void print_opp_meas(void)
{
3482 3483 3484
  int sfn=0;
  print_meas(&softmodem_stats_mt, "Main ENB Thread", NULL, NULL);
  print_meas(&softmodem_stats_hw, "HW Acquisation", NULL, NULL);
3485

3486 3487 3488 3489 3490
  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);
  }
}