lte-softmodem.c 112 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
double sample_rate=30.72e6;
286
double bw = 10.0e6;
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
unsigned int samples_per_frame = 307200;
295
unsigned int tx_forward_nsamps=0;
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 588
      //fl_set_object_label(form_stats->stats_text, stats_buffer);
      fl_clear_browser(form_stats->stats_text);
      fl_add_browser_line(form_stats->stats_text, stats_buffer);
589

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

598
    }
599

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

605
  //  printf("%s",stats_buffer);
606

607
# ifdef ENABLE_XFORMS_WRITE_STATS
608

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

623
# endif
624

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

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

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

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

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

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

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

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

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

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

672 673 674

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

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

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

  pthread_exit((void*) arg);

}

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

jiangx's avatar
jiangx committed
714
  int channel_buffer_size,ret;
715

716 717 718
  time_t timer;
  struct tm *now;

719
  struct sched_param sched_param;
720 721

  sched_param.sched_priority = sched_get_priority_max(SCHED_FIFO)-1;
722
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
723

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

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

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

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


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

  dumpfile_id = fopen(dumpfile_name,"w");
756 757 758 759 760

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


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

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

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

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

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

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

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

818 819 820
  free(fifo2file_buffer);
  fclose(dumpfile_id);
  close(fifo);
821

822 823 824 825 826
  pthread_exit((void*) arg);

}
#endif

827 828


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

845 846 847 848 849
    LOG_D(EMU,"\n");
  }
}
#endif

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

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
858

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

868 869 870
      itti_receive_msg (TASK_L2L1, &message_p);

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

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

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
924
  return NULL;
925 926 927
}
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
928

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

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

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
947

Raymond Knopp's avatar
 
Raymond Knopp committed
948
    for (aa=0; aa<phy_vars_eNB->lte_frame_parms.nb_antennas_tx; aa++) {
949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966
      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));
967 968 969 970 971 972
	// if S-subframe generate first slot only
	if (subframe_select(&phy_vars_eNB->lte_frame_parms,subframe) == SF_DL)
	  normal_prefix_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F+slot_sizeF],
			    dummy_tx_b+(phy_vars_eNB->lte_frame_parms.samples_per_tti>>1),
			    7,
			    &(phy_vars_eNB->lte_frame_parms));
Raymond Knopp's avatar
 
Raymond Knopp committed
973
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
974

975 976 977 978 979 980 981
      // if S-subframe generate first slot only
      if (subframe_select(&phy_vars_eNB->lte_frame_parms,subframe) == SF_S)
	len = phy_vars_eNB->lte_frame_parms.samples_per_tti>>1;
      else
	len = phy_vars_eNB->lte_frame_parms.samples_per_tti;
 
     for (i=0; i<len; i++) {
982 983 984 985 986 987 988 989 990
        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
991
#ifdef EXMIMO
992
          ((short*)dummy_tx_b)[2*i]<<4;
993 994
#elif OAI_BLADRF
	((short*)dummy_tx_b)[2*i];
Raymond Knopp's avatar
 
Raymond Knopp committed
995
#else
996
          ((short*)dummy_tx_b)[2*i]<<5;
Raymond Knopp's avatar
 
Raymond Knopp committed
997
#endif
998
	  ((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[1]=
Raymond Knopp's avatar
 
Raymond Knopp committed
999
#ifdef EXMIMO
1000 1001 1002
	    ((short*)dummy_tx_b)[2*i+1]<<4;
#elif OAI_BLADRF
	  ((short*)dummy_tx_b)[2*i+1];
Raymond Knopp's avatar
 
Raymond Knopp committed
1003
#else
1004
	  ((short*)dummy_tx_b)[2*i+1]<<5;
Raymond Knopp's avatar
 
Raymond Knopp committed
1005
#endif
1006 1007 1008 1009 1010 1011 1012
     }
     // if S-subframe switch to RX in second subframe
     if (subframe_select(&phy_vars_eNB->lte_frame_parms,subframe) == SF_S) {
       for (i=0; i<len; i++) {
	 phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset++] = 0x00010001;
       }
     }
Raymond Knopp's avatar
 
Raymond Knopp committed
1013 1014 1015 1016
    }
  }
}

1017 1018 1019 1020 1021 1022 1023 1024 1025
/* 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
1026

1027 1028 1029 1030 1031 1032 1033 1034 1035
/*!
 * \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
1036 1037

  eNB_proc_t *proc = (eNB_proc_t*)param;
1038 1039 1040 1041 1042 1043
  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");
  }
1044 1045 1046
  // set default return value
  eNB_thread_tx_status[proc->subframe] = 0;

Raymond Knopp's avatar
 
Raymond Knopp committed
1047 1048
#ifdef RTAI
  RT_TASK *task;
1049
  char task_name[8];
Raymond Knopp's avatar
 
Raymond Knopp committed
1050

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

1054 1055 1056
  if (task == NULL) {
    LOG_E(PHY,"[SCHED][eNB] Problem starting eNB_proc_TX thread_index %d (%s)!!!!\n",proc->subframe,task_name);
    return 0;
1057 1058 1059 1060 1061
  } else {
    LOG_I(PHY,"[SCHED][eNB] eNB TX thread CC %d SF %d started with id %p\n",
          proc->CC_id,
          proc->subframe,
          task);
1062
  }
1063

Raymond Knopp's avatar
 
Raymond Knopp committed
1064
#else
1065
#ifdef LOWLATENCY
1066 1067 1068
  struct sched_attr attr;
  unsigned int flags = 0;

1069 1070 1071 1072
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1073

1074 1075 1076
  // 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
1077 1078
  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
1079

1080 1081 1082 1083
  if (sched_setattr(0, &attr, flags) < 0 ) {
    perror("[SCHED] eNB tx thread: sched_setattr failed\n");
    return &eNB_thread_tx_status[proc->subframe];
  }
1084

1085
  LOG_I( HW, "[SCHED] eNB TX deadline thread %d(Tid %ld) started on CPU %d\n", proc->subframe, gettid(), sched_getcpu() );
1086
#else
1087
  LOG_I( HW, "[SCHED][eNB] TX thread %d started on CPU %d TID %d\n", proc->subframe, sched_getcpu(),gettid() );
1088 1089
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
1090 1091 1092 1093 1094 1095 1096 1097
#endif

  mlockall(MCL_CURRENT | MCL_FUTURE);

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

1098
  while (!oai_exit) {
1099

1100
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe), 0 );
1101

1102
    if (pthread_mutex_lock(&proc->mutex_tx) != 0) {
1103
      LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc %d\n", proc->subframe );
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1104
      exit_fun("nothing to add");
1105
      break;
1106
    }
1107

1108
    while (proc->instance_cnt_tx < 0) {
1109 1110 1111
      // 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
1112
    }
1113

1114 1115 1116 1117 1118
    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
1119

1120 1121
    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 );
1122 1123 1124
    start_meas( &softmodem_stats_tx_sf[proc->subframe] );

    if (oai_exit) break;
1125

1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137
    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;
      }
1138 1139
      /* wait for our turn or oai_exit */
      while (sync_phy_proc[proc->subframe].phy_proc_CC_id != proc->CC_id && !oai_exit) {
1140 1141 1142
        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
1143

1144 1145 1146 1147 1148 1149 1150 1151
      if (oai_exit) {
        if (pthread_mutex_unlock(&sync_phy_proc[proc->subframe].mutex_phy_proc_tx) != 0) {
          LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc %d\n", proc->subframe);
          exit_fun("nothing to add");
        }
        break;
      }

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

1154 1155 1156 1157 1158
      /* 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) {
1159
        LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc %d\n", proc->subframe);
1160 1161 1162
        exit_fun("nothing to add");
        break;
      }
1163
    }
1164

1165
    do_OFDM_mod_rt( proc->subframe_tx, PHY_vars_eNB_g[0][proc->CC_id] );
1166

1167 1168 1169 1170 1171
    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
1172

1173 1174 1175 1176 1177 1178 1179 1180 1181
    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++;
1182

1183 1184 1185
    if (proc->frame_tx==1024)
      proc->frame_tx=0;

1186 1187 1188
    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);

1189 1190 1191
  }

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1194 1195 1196
#ifdef HARD_RT
  rt_make_soft_real_time();
#endif
1197

Raymond Knopp's avatar
 
Raymond Knopp committed
1198
#ifdef DEBUG_THREADS
1199
  printf( "Exiting eNB thread TX %d\n", proc->subframe );
Raymond Knopp's avatar
 
Raymond Knopp committed
1200 1201 1202 1203 1204
#endif
  // clean task
#ifdef RTAI
  rt_task_delete(task);
#endif
1205

1206 1207
  eNB_thread_tx_status[proc->subframe] = 0;
  return &eNB_thread_tx_status[proc->subframe];
Raymond Knopp's avatar
 
Raymond Knopp committed
1208 1209 1210
}


1211 1212 1213 1214 1215 1216 1217 1218 1219 1220
/*!
 * \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
1221
  eNB_proc_t *proc = (eNB_proc_t*)param;
1222

1223 1224
  FILE  *rx_time_file;
  char rx_time_name[101];
Raymond Knopp's avatar
 
Raymond Knopp committed
1225 1226
  int i;

1227 1228 1229 1230
  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");
  }
1231 1232 1233
  // set default return value
  eNB_thread_rx_status[proc->subframe] = 0;

Raymond Knopp's avatar
 
Raymond Knopp committed
1234 1235
#ifdef RTAI
  RT_TASK *task;
1236
  char task_name[8];
Raymond Knopp's avatar
 
Raymond Knopp committed
1237

1238
  sprintf(task_name,"RXC%1dS%1d",proc->CC_id,proc->subframe);
Raymond Knopp's avatar
 
Raymond Knopp committed
1239 1240 1241
  task = rt_task_init_schmod(nam2num(task_name), 0, 0, 0, SCHED_FIFO, 0xF);

  if (task==NULL) {
1242 1243
    LOG_E(PHY,"[SCHED][eNB] Problem starting eNB_proc_RX thread_index %d (%s)!!!!\n",proc->subframe,task_name);
    return 0;
1244
  } else {
1245
    LOG_I(PHY,"[SCHED][eNB] eNB RX thread CC_id %d SF %d started with id %p\n", /*  on CPU %d*/
1246 1247 1248
          proc->CC_id,
          proc->subframe,
          task); /*,rtai_cpuid()*/
Raymond Knopp's avatar
 
Raymond Knopp committed
1249
  }
1250

Raymond Knopp's avatar
 
Raymond Knopp committed
1251
#else
1252
#ifdef LOWLATENCY
1253 1254 1255
  struct sched_attr attr;
  unsigned int flags = 0;

1256 1257 1258 1259
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1260

Navid Nikaein's avatar
Navid Nikaein committed
1261
  /* This creates a 2ms reservation every 10ms period*/
1262
  attr.sched_policy = SCHED_DEADLINE;
1263 1264
  attr.sched_runtime  = 1   *  1000000; // each rx thread must finish its job in the worst case in 2ms
  attr.sched_deadline = 1   *  1000000; // each rx thread will finish within 2ms
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1265
  attr.sched_period   = 1   * 10000000; // each rx thread has a period of 10ms from the starting point
1266 1267

  if (sched_setattr(0, &attr, flags) < 0 ) {
1268
    perror("[SCHED] eNB RX sched_setattr failed\n");
1269
    return &eNB_thread_rx_status[proc->subframe];
1270
  }
1271

1272
  LOG_I( HW, "[SCHED] eNB RX deadline thread %d(TID %ld) started on CPU %d\n", proc->subframe, gettid(), sched_getcpu() );
1273
#else
1274
  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
1275
#endif
1276
#endif // RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
1277 1278 1279 1280 1281 1282 1283

  mlockall(MCL_CURRENT | MCL_FUTURE);

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

1284
  while (!oai_exit) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1285

1286
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 0 );
1287

Raymond Knopp's avatar
 
Raymond Knopp committed
1288
    if (pthread_mutex_lock(&proc->mutex_rx) != 0) {
1289 1290 1291
      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
1292 1293
    }

1294
    while (proc->instance_cnt_rx < 0) {
1295 1296 1297
      // 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
1298
    }
1299 1300 1301 1302 1303 1304 1305

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

1306 1307
    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 );
1308
    start_meas( &softmodem_stats_rx_sf[proc->subframe] );
1309

Raymond Knopp's avatar
 
Raymond Knopp committed
1310
    if (oai_exit) break;
1311

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

1315
      phy_procedures_eNB_RX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay );
Raymond Knopp's avatar
 
Raymond Knopp committed
1316
    }
1317 1318

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1322
    if (pthread_mutex_lock(&proc->mutex_rx) != 0) {
1323 1324 1325
      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
1326
    }
1327 1328 1329 1330 1331 1332 1333

    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
1334
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1335 1336

    proc->frame_rx++;
1337

Raymond Knopp's avatar
 
Raymond Knopp committed
1338 1339
    if (proc->frame_rx==1024)
      proc->frame_rx=0;
1340

1341 1342 1343
    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
1344
  }
1345 1346

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1349
#ifdef HARD_RT
Raymond Knopp's avatar
 
Raymond Knopp committed
1350 1351 1352 1353
  rt_make_soft_real_time();
#endif

#ifdef DEBUG_THREADS
1354
  printf( "Exiting eNB thread RX %d\n", proc->subframe );
Raymond Knopp's avatar
 
Raymond Knopp committed
1355 1356 1357 1358
#endif
  // clean task
#ifdef RTAI
  rt_task_delete(task);
Raymond Knopp's avatar
 
Raymond Knopp committed
1359 1360
#endif

1361 1362
  eNB_thread_rx_status[proc->subframe] = 0;
  return &eNB_thread_rx_status[proc->subframe];
Raymond Knopp's avatar
 
Raymond Knopp committed
1363 1364 1365 1366
}



Raymond Knopp's avatar
 
Raymond Knopp committed
1367

1368 1369
void init_eNB_proc(void)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1370
  int i;
Raymond Knopp's avatar
 
Raymond Knopp committed
1371 1372
  int CC_id;

1373 1374 1375 1376
  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] );
1377

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

1381
      pthread_attr_init( &attr_eNB_proc_rx[CC_id][i] );
1382

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

1386
#ifndef LOWLATENCY
1387
      // set the kernel scheduling policy and priority
Raymond Knopp's avatar
 
Raymond Knopp committed
1388 1389 1390 1391 1392 1393
      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);
1394
      printf("Setting OS scheduler to SCHED_FIFO for eNB [cc%d][thread%d] \n",CC_id, i);
1395 1396
#endif

1397 1398 1399
      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
1400
      PHY_vars_eNB_g[0][CC_id]->proc[i].CC_id = CC_id;
1401 1402 1403 1404 1405 1406
      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] );
1407 1408 1409 1410 1411
      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
1412 1413
      PHY_vars_eNB_g[0][CC_id]->proc[i].frame_tx = 0;
      PHY_vars_eNB_g[0][CC_id]->proc[i].frame_rx = 0;
1414
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
1415 1416
      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
1417
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
1418 1419
      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
1420
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1421
    }
1422 1423


1424
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
1425 1426
    // 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
1427

Raymond Knopp's avatar
 
Raymond Knopp committed
1428
    //PHY_vars_eNB_g[0][CC_id]->proc[0].frame_rx = 1023;
Raymond Knopp's avatar
 
Raymond Knopp committed
1429 1430
    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
1431
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
1432 1433
    // 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
1434
    //    PHY_vars_eNB_g[0][CC_id]->proc[7].frame_tx = 1;
Raymond Knopp's avatar
 
Raymond Knopp committed
1435 1436
    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
1437
    //    PHY_vars_eNB_g[0][CC_id]->proc[0].frame_tx = 1;
Raymond Knopp's avatar
 
Raymond Knopp committed
1438
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1439
  }
1440 1441 1442 1443 1444 1445 1446

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

1449 1450 1451 1452 1453 1454
/*!
 * \brief Terminate eNB TX and RX threads.
 */
void kill_eNB_proc(void)
{
  int *status;
Raymond Knopp's avatar
 
Raymond Knopp committed
1455

1456 1457
  for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++)
    for (int i=0; i<NUM_ENB_THREADS; i++) {
1458

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1472
#ifdef DEBUG_THREADS
1473

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1488
#ifdef DEBUG_THREADS
1489
      printf( "Killing RX CC_id %d thread %d\n", CC_id, i );
Raymond Knopp's avatar
 
Raymond Knopp committed
1490
#endif
1491 1492 1493 1494

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

1500 1501
#ifdef DEBUG_THREADS

1502 1503 1504 1505 1506 1507 1508 1509 1510
      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" );
        }
      }
1511

1512 1513
#else
      UNUSED(result)
Raymond Knopp's avatar
 
Raymond Knopp committed
1514
#endif
1515 1516 1517 1518 1519

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


Raymond Knopp's avatar
 
Raymond Knopp committed
1524 1525


1526

Raymond Knopp's avatar
 
Raymond Knopp committed
1527

1528 1529 1530 1531 1532 1533
/*!
 * \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 )
1534
{
1535 1536
  UNUSED(arg);
  static int eNB_thread_status;
1537

1538
  unsigned char slot;
1539
#ifdef EXMIMO
1540
  slot=0;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1541
  RTIME time_in;
Raymond Knopp's avatar
 
Raymond Knopp committed
1542
  volatile unsigned int *DAQ_MBOX = openair0_daq_cnt();
Raymond Knopp's avatar
 
Raymond Knopp committed
1543 1544
  int mbox_target=0,mbox_current=0;
  int hw_slot,delay_cnt;
Raymond Knopp's avatar
 
Raymond Knopp committed
1545 1546
  int diff;
  int ret;
1547
  int first_run=1;
Raymond Knopp's avatar
 
Raymond Knopp committed
1548
#else
1549 1550 1551
  // the USRP implementation operates on subframes, not slots
  // one subframe consists of one even and one odd slot
  slot = 1;
1552
  int spp;
1553
  int tx_launched = 0;
1554 1555 1556

  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
1557

1558
  int hw_subframe = 0; // 0..NUM_ENB_THREADS-1 => 0..9
1559
  spp = openair0_cfg[0].samples_per_packet;
1560 1561
  unsigned int rx_pos = 0;
  unsigned int tx_pos = spp*tx_delay;
Raymond Knopp's avatar
 
Raymond Knopp committed
1562
#endif
1563
  int CC_id=0;	
1564
  struct timespec trx_time0, trx_time1, trx_time2;
1565

1566
#ifdef RTAI
1567
  RT_TASK* task = rt_task_init_schmod(nam2num("eNBmain"), 0, 0, 0, SCHED_FIFO, 0xF);
1568
#else
1569
#ifdef LOWLATENCY
1570 1571 1572
  struct sched_attr attr;
  unsigned int flags = 0;

Raymond Knopp's avatar
 
Raymond Knopp committed
1573 1574 1575 1576
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1577

Raymond Knopp's avatar
 
Raymond Knopp committed
1578 1579
  /* This creates a .5 ms  reservation */
  attr.sched_policy = SCHED_DEADLINE;
1580 1581
  attr.sched_runtime  = 0.2 * 1000000;
  attr.sched_deadline = 0.9 * 1000000;
1582 1583
  attr.sched_period   = 1.0 * 1000000;

Lionel Gauthier's avatar
Lionel Gauthier committed
1584

Raymond Knopp's avatar
 
Raymond Knopp committed
1585 1586 1587 1588
  /* 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");
     }*/
1589

1590
  if (sched_setattr(0, &attr, flags) < 0 ) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1591 1592 1593 1594
    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",
1595
          gettid(),sched_getcpu());
Raymond Knopp's avatar
 
Raymond Knopp committed
1596
  }
1597

1598
#endif
1599 1600
#endif

1601 1602 1603 1604 1605
  // stop early, if an exit is requested
  // FIXME really neccessary?
  if (oai_exit)
    goto eNB_thread_cleanup;

1606
#ifdef RTAI
1607
  printf( "[SCHED][eNB] Started eNB main thread (id %p)\n", task );
Raymond Knopp's avatar
 
Raymond Knopp committed
1608
#else
1609
  printf( "[SCHED][eNB] Started eNB main thread on CPU %d TID %d\n", sched_getcpu(), gettid());
1610 1611 1612
#endif

#ifdef HARD_RT
1613
  rt_make_hard_real_time();
1614 1615
#endif

1616 1617 1618 1619 1620 1621 1622 1623
  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;
1624

1625 1626
  printf( "waiting for sync (eNB_thread)\n" );
  pthread_mutex_lock( &sync_mutex );
1627

1628 1629
  while (sync_var<0)
    pthread_cond_wait( &sync_cond, &sync_mutex );
1630

1631
  pthread_mutex_unlock(&sync_mutex);
1632

1633
  int frame = 0;
1634

1635 1636
  while (!oai_exit) {
    start_meas( &softmodem_stats_mt );
Raymond Knopp's avatar
 
Raymond Knopp committed
1637

1638
#ifdef EXMIMO
1639 1640
    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]);
1641 1642
    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);
1643 1644 1645 1646
    //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];
1647

1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658
    //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;
1659

1660 1661
      if (diff<0)
        diff = diff +150;
1662

1663 1664 1665 1666
      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)))) {
1667

1668 1669 1670 1671
      // 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);
      
1672
      if (exit_missed_slots==1) {
1673 1674
        stop_meas(&softmodem_stats_mt);
        exit_fun("[HW][eNB] missed slot");
1675
      } else {
1676
        num_missed_slots++;
1677
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_MISSED_SLOTS_ENB,num_missed_slots );
1678
      }
1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700

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

    
1701
    }
1702

1703
    if (diff>8)
1704 1705
      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);
1706

1707 1708
    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);
1709 1710

    delay_cnt = 0;
1711

1712 1713 1714 1715
    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);
1716
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP,1);
1717
      ret = rt_sleep_ns(diff*DAQ_PERIOD);
1718 1719
      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);
1720

1721 1722
      if (ret)
        LOG_D(HW,"eNB Frame %d, time %llu: rt_sleep_ns returned %d\n",frame, time_in);
1723

Raymond Knopp's avatar
 
Raymond Knopp committed
1724
      hw_slot = (((((volatile unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15;
1725 1726 1727
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME, hw_slot>>1);
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME, frame);
//LOG_D(HW,"eNB Frame %d : hw_slot %d, time %llu\n",frame,hw_slot,rt_get_time_ns());
1728
      delay_cnt++;
1729

1730 1731 1732 1733 1734
      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");
      }
1735

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1738
      if ((mbox_current>=135) && (mbox_target<15)) //handle the frame wrap-arround
1739
        diff = 150-mbox_current+mbox_target;
Raymond Knopp's avatar
 
Raymond Knopp committed
1740
      else if ((mbox_current<15) && (mbox_target>=135))
1741
        diff = -150+mbox_target-mbox_current;
Raymond Knopp's avatar
 
Raymond Knopp committed
1742
      else
1743 1744
        diff = mbox_target - mbox_current;
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1745

1746
#else  // EXMIMO
1747 1748
    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 );
1749
    tx_launched = 0;
1750

1751
    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
1752

1753
      unsigned int rxs;
Raymond Knopp's avatar
 
Raymond Knopp committed
1754
#ifndef USRP_DEBUG
1755 1756 1757
      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
1758

1759
      clock_gettime( CLOCK_MONOTONIC, &trx_time0 );
1760

1761 1762 1763
      // 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];
1764

1765
      start_meas( &softmodem_stats_hw );
1766

1767
      openair0_timestamp timestamp;
1768 1769 1770 1771 1772 1773 1774
      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
1775

1776 1777 1778 1779
      if (frame > 10){ 
	if (rxs != spp)
	  exit_fun( "problem receiving samples" );
      }
1780
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
1781

1782
      // Transmit TX buffer based on timestamp from RX
1783
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794

      // 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,
1795
                                1);
Raymond Knopp's avatar
 
Raymond Knopp committed
1796 1797
      }

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

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

1804
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE,0);
1805 1806 1807 1808 1809 1810 1811 1812
#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;
1813

1814
        for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849
          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
1850 1851

#endif // USRP
1852

1853
    if (oai_exit) break;
Raymond Knopp's avatar
 
Raymond Knopp committed
1854

1855 1856 1857 1858 1859
    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;
1860

1861 1862
      if (time_diff < timing_info.time_min)
        timing_info.time_min = time_diff;
1863

1864 1865
      if (time_diff > timing_info.time_max)
        timing_info.time_max = time_diff;
1866

1867 1868 1869 1870 1871 1872
      timing_info.time_avg += time_diff;
    }

    timing_info.n_samples++;

    if ((slot&1) == 1) {
1873
      // odd slot
1874
#ifdef EXMIMO
1875
      int sf = ((slot>>1)+1)%10;
Raymond Knopp's avatar
 
Raymond Knopp committed
1876
#else
1877
      int sf = hw_subframe;
Raymond Knopp's avatar
 
Raymond Knopp committed
1878
#endif
1879 1880

      for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1881 1882
#ifdef EXMIMO

1883 1884
        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);
1885 1886
        } 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);
1887 1888
          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);
1889

1890 1891 1892 1893
          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);
            }
1894
          } else {
1895 1896 1897 1898
            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");
          }
        }
1899

Raymond Knopp's avatar
 
Raymond Knopp committed
1900 1901
#endif

1902 1903 1904 1905 1906
        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
1907

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

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

1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923
        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
1924
      }
1925 1926 1927 1928
    }

#ifdef EXMIMO
    slot++;
1929

1930 1931 1932 1933
    if (slot == 20) {
      frame++;
      slot = 0;
    }
1934

Raymond Knopp's avatar
 
Raymond Knopp committed
1935
#else
1936 1937
    hw_subframe++;
    slot += 2;
1938

1939
    if (hw_subframe == NUM_ENB_THREADS) {
1940
      // the radio frame is complete, start over
1941 1942 1943 1944
      hw_subframe = 0;
      frame++;
      slot = 1;
    }
1945 1946

#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1947

1948
#if defined(ENABLE_ITTI)
1949
    itti_update_lte_time( frame, slot );
1950
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1951
  }
1952 1953

eNB_thread_cleanup:
Raymond Knopp's avatar
 
Raymond Knopp committed
1954
#ifdef DEBUG_THREADS
1955
  printf( "eNB_thread: finished, ran %d times.\n", frame );
Raymond Knopp's avatar
 
Raymond Knopp committed
1956
#endif
1957

1958
#ifdef HARD_RT
Raymond Knopp's avatar
 
Raymond Knopp committed
1959
  rt_make_soft_real_time();
1960 1961
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
1962
#ifdef DEBUG_THREADS
1963
  printf( "Exiting eNB_thread ..." );
Raymond Knopp's avatar
 
Raymond Knopp committed
1964 1965
#endif
  // clean task
1966
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
1967
  rt_task_delete(task);
1968
#endif
1969 1970 1971

  eNB_thread_status = 0;
  return &eNB_thread_status;
Raymond Knopp's avatar
 
Raymond Knopp committed
1972
}
1973

1974

Raymond Knopp's avatar
 
Raymond Knopp committed
1975

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1976

1977 1978
static void get_options (int argc, char **argv)
{
1979 1980 1981
  int c;
  //  char                          line[1000];
  //  int                           l;
1982
  int k,i;//,j,k;
1983
#if defined(OAI_USRP) || defined(CPRIGW)
1984
  int clock_src;
1985
#endif
1986 1987 1988 1989 1990
  int CC_id;
#ifdef EXMIMO
  char rxg_fname[256], line[1000];
  FILE *rxg_fd;
  int l;
1991
#endif
1992 1993 1994



1995 1996

  const Enb_properties_array_t *enb_properties;
1997

1998 1999 2000 2001 2002 2003 2004
  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,
2005
    LONG_OPTION_NO_L2_CONNECT,
Raymond Knopp's avatar
 
Raymond Knopp committed
2006
    LONG_OPTION_CALIB_PRACH_TX,
2007 2008
    LONG_OPTION_RXGAIN,
    LONG_OPTION_TXGAIN,
2009 2010
    LONG_OPTION_SCANCARRIER,
    LONG_OPTION_MAXPOWER
2011
  };
2012

2013 2014 2015 2016 2017 2018 2019
  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
2020 2021 2022 2023
    {"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},
2024
    {"ue-max-power",   required_argument,  NULL, LONG_OPTION_MAXPOWER},
2025 2026 2027
    {NULL, 0, NULL, 0}
  };

2028
  while ((c = getopt_long (argc, argv, "C:dK:g:F:G:hqO:m:SUVRM:r:P:Ws:t:x:",long_options,NULL)) != -1) {
2029
    switch (c) {
2030 2031 2032 2033 2034
    case LONG_OPTION_MAXPOWER:
      tx_max_power[0]=atoi(optarg);
      for (CC_id=1;CC_id<MAX_NUM_CCs;CC_id++)
	tx_max_power[CC_id]=tx_max_power[0];

2035 2036 2037 2038
    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;
2039

2040 2041 2042 2043 2044
    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;
2045

2046 2047 2048 2049
    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
2050
      break;
2051

2052 2053 2054 2055 2056
    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;
2057

2058 2059 2060
    case LONG_OPTION_DEBUG_UE_PRACH:
      mode = debug_prach;
      break;
2061

2062 2063 2064
    case LONG_OPTION_NO_L2_CONNECT:
      mode = no_L2_connect;
      break;
2065

Raymond Knopp's avatar
 
Raymond Knopp committed
2066 2067 2068 2069
    case LONG_OPTION_CALIB_PRACH_TX:
      mode = calib_prach_tx;
      break;

2070
    case LONG_OPTION_RXGAIN:
2071 2072
      for (i=0; i<4; i++)
        rx_gain[0][i] = atof(optarg);
2073

2074
      break;
2075

2076 2077 2078
    case LONG_OPTION_TXGAIN:
      for (i=0; i<4; i++)
        tx_gain[0][i] = atof(optarg);
2079

2080
      break;
2081

2082 2083 2084 2085 2086
    case LONG_OPTION_SCANCARRIER:
      UE_scan_carrier=1;

      break;

2087 2088 2089
    case 'M':
#ifdef ETHERNET
      strcpy(rrh_eNB_ip,optarg);
2090
#endif
2091
      break;
2092

2093
    case 'C':
2094 2095 2096 2097 2098 2099
      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]);
2100
      }
2101

2102
      UE_scan=0;
2103

2104
      break;
2105

2106 2107 2108 2109
    case 'd':
#ifdef XFORMS
      do_forms=1;
      printf("Running with XFORMS!\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2110
#endif
2111
      break;
2112

2113 2114 2115
    case 'K':
#if defined(ENABLE_ITTI)
      itti_dump_file = strdup(optarg);
2116
#else
2117
      printf("-K option is disabled when ENABLE_ITTI is not defined\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2118
#endif
2119
      break;
2120

2121 2122 2123
    case 'O':
      conf_config_file_name = optarg;
      break;
2124

2125 2126 2127
    case 'U':
      UE_flag = 1;
      break;
2128

2129 2130 2131
    case 'm':
      target_dl_mcs = atoi (optarg);
      break;
2132

2133 2134 2135
    case 't':
      target_ul_mcs = atoi (optarg);
      break;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2136
#ifdef OPENAIR2
2137

2138 2139 2140 2141 2142 2143 2144
    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");
      /*
2145 2146 2147
      if (optarg == NULL){
      in_ip[0] =NULL;
      printf("Enabling OPT for wireshark for local interface");
2148
      } else {
2149 2150 2151
      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);
2152 2153 2154
      }
      */
      break;
2155

2156
    case 'P':
2157 2158
      opt_type = OPT_PCAP;
      opt_enabled=1;
2159 2160 2161 2162 2163

      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");
2164
      } else {
2165 2166 2167
        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);
2168
      }
2169 2170

      break;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2171
#endif
2172

Raymond Knopp's avatar
 
Raymond Knopp committed
2173 2174 2175
    case 'V':
      ouput_vcd = 1;
      break;
2176

Raymond Knopp's avatar
 
Raymond Knopp committed
2177
    case  'q':
Raymond Knopp's avatar
 
Raymond Knopp committed
2178 2179
      opp_enabled = 1;
      break;
2180

Raymond Knopp's avatar
 
Raymond Knopp committed
2181 2182 2183
    case  'R' :
      online_log_messages =1;
      break;
2184

Raymond Knopp's avatar
 
Raymond Knopp committed
2185
    case 'r':
2186
      UE_scan = 0;
2187

2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213
      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
2214
      }
2215

2216
      break;
2217

Raymond Knopp's avatar
 
Raymond Knopp committed
2218
    case 's':
2219
#if defined(OAI_USRP) || defined(CPRIGW)
Raymond Knopp's avatar
 
Raymond Knopp committed
2220 2221

      clock_src = atoi(optarg);
2222

Raymond Knopp's avatar
 
Raymond Knopp committed
2223
      if (clock_src == 0) {
2224 2225 2226 2227 2228
        //  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
2229
      }
2230

Raymond Knopp's avatar
 
Raymond Knopp committed
2231 2232 2233 2234
#else
      printf("Note: -s not defined for ExpressMIMO2\n");
#endif
      break;
2235

2236 2237 2238 2239
    case 'S':
      exit_missed_slots=0;
      printf("Skip exit for missed slots\n");
      break;
2240

2241
    case 'g':
Raymond Knopp's avatar
 
Raymond Knopp committed
2242
      glog_level=atoi(optarg); // value between 1 - 9
2243
      break;
2244 2245

    case 'F':
2246
#ifdef EXMIMO
2247 2248
      sprintf(rxg_fname,"%srxg.lime",optarg);
      rxg_fd = fopen(rxg_fname,"r");
2249

2250
      if (rxg_fd) {
2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268
        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);

2269
#endif
2270
      break;
2271

2272 2273 2274
    case 'G':
      glog_verbosity=atoi(optarg);// value from 0, 0x5, 0x15, 0x35, 0x75
      break;
2275

2276 2277
    case 'x':
      transmission_mode = atoi(optarg);
2278

2279
      if (transmission_mode > 2) {
2280 2281
        printf("Transmission mode > 2 (%d) not supported for the moment\n",transmission_mode);
        exit(-1);
2282
      }
2283

2284
      break;
2285 2286 2287 2288
    case 'h':
      help ();
      exit (-1);
       
Raymond Knopp's avatar
 
Raymond Knopp committed
2289
    default:
2290 2291
      help ();
      exit (-1);
Raymond Knopp's avatar
 
Raymond Knopp committed
2292
      break;
2293 2294
    }
  }
2295

Raymond Knopp's avatar
 
Raymond Knopp committed
2296 2297
  if (UE_flag == 0)
    AssertFatal(conf_config_file_name != NULL,"Please provide a configuration file\n");
2298 2299


Raymond Knopp's avatar
 
Raymond Knopp committed
2300
  if ((UE_flag == 0) && (conf_config_file_name != NULL)) {
2301
    int i,j;
2302

Raymond Knopp's avatar
 
Raymond Knopp committed
2303
    NB_eNB_INST = 1;
2304

Raymond Knopp's avatar
 
Raymond Knopp committed
2305 2306
    /* Read eNB configuration file */
    enb_properties = enb_config_init(conf_config_file_name);
2307

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

Raymond Knopp's avatar
 
Raymond Knopp committed
2312
    /* Update some simulation parameters */
2313
    for (i=0; i < enb_properties->number; i++) {
2314
      AssertFatal (MAX_NUM_CCs == enb_properties->properties[i]->nb_cc,
2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331
                   "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
2332 2333
      }

2334

2335
#ifdef OPENAIR2
2336

2337 2338 2339
      init_all_otg(0);
      g_otg->seed = 0;
      init_seeds(g_otg->seed);
2340 2341 2342 2343 2344 2345 2346 2347 2348 2349

      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");
2350
      }
2351

2352
      init_predef_traffic(enb_properties->properties[i]->num_otg_elements, 1);
2353

2354
#endif
2355

2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369
      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
2370 2371 2372 2373 2374 2375
# 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
2376 2377 2378
#if defined (ENABLE_SECURITY)
      osa_log_level                  = enb_properties->properties[i]->osa_log_level;
      osa_log_verbosity              = enb_properties->properties[i]->osa_log_verbosity;
2379
#endif
Florian Kaltenberger's avatar
Florian Kaltenberger committed
2380

Raymond Knopp's avatar
 
Raymond Knopp committed
2381
      // adjust the log
2382
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
2383 2384 2385 2386 2387 2388 2389 2390 2391 2392
        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
2393
      } // CC_id
2394
    }// i
2395
  } else if ((UE_flag == 1) && (conf_config_file_name != NULL)) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2396 2397 2398 2399 2400 2401

    // 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
2402
}
2403

2404 2405
int main( int argc, char **argv )
{
Raymond Knopp's avatar
 
Raymond Knopp committed
2406
  int i,aa,card;
Lionel Gauthier's avatar
Lionel Gauthier committed
2407
#if defined (XFORMS) || defined (EMOS) || defined (EXMIMO)
Raymond Knopp's avatar
 
Raymond Knopp committed
2408
  void *status;
2409
#endif
2410

Raymond Knopp's avatar
 
Raymond Knopp committed
2411
  int CC_id;
Raymond Knopp's avatar
 
Raymond Knopp committed
2412
  uint16_t Nid_cell = 0;
2413
  uint8_t  cooperation_flag=0,  abstraction_flag=0;
2414
#ifndef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
2415
  uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2;
2416 2417 2418
#endif

#ifdef ENABLE_TCXO
Raymond Knopp's avatar
 
Raymond Knopp committed
2419
  unsigned int tcxo = 114;
2420 2421
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
2422
#if defined (XFORMS)
2423 2424
  int ret;
#endif
2425
#if defined (EMOS) || (! defined (RTAI))
Raymond Knopp's avatar
 
Raymond Knopp committed
2426
  int error_code;
2427
#endif
2428

2429 2430 2431 2432 2433
#ifdef DEBUG_CONSOLE
  setvbuf(stdout, NULL, _IONBF, 0);
  setvbuf(stderr, NULL, _IONBF, 0);
#endif

2434 2435 2436
  PHY_VARS_UE *UE[MAX_NUM_CCs];

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

2439
  memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
Raymond Knopp's avatar
 
Raymond Knopp committed
2440
  set_latency_target();
2441

2442

2443

2444
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2445 2446
    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 */
2447
    frame_parms[CC_id]->frame_type         = FDD; /* TDD */
Raymond Knopp's avatar
 
Raymond Knopp committed
2448 2449
    frame_parms[CC_id]->tdd_config          = 3;
    frame_parms[CC_id]->tdd_config_S        = 0;
2450 2451
    frame_parms[CC_id]->N_RB_DL             = 100;
    frame_parms[CC_id]->N_RB_UL             = 100;
Raymond Knopp's avatar
 
Raymond Knopp committed
2452
    frame_parms[CC_id]->Ncp                 = NORMAL;
Raymond Knopp's avatar
 
Raymond Knopp committed
2453 2454
    frame_parms[CC_id]->Ncp_UL              = NORMAL;
    frame_parms[CC_id]->Nid_cell            = Nid_cell;
Raymond Knopp's avatar
 
Raymond Knopp committed
2455
    frame_parms[CC_id]->num_MBSFN_config    = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2456 2457 2458
    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
2459
  }
2460

2461 2462 2463 2464 2465
  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];
2466
    //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
2467
  }
2468 2469
  logInit();
 
2470
  get_options (argc, argv); //Command-line options
2471 2472 2473 2474 2475
 
  // initialize mscgen log
  MSC_INIT(MSC_E_UTRAN);
  
  // initialize the log (see log.h for details)
Florian Kaltenberger's avatar
Florian Kaltenberger committed
2476 2477
  set_glog(glog_level, glog_verbosity);

2478 2479
  //randominit (0);
  set_taus_seed (0);
Raymond Knopp's avatar
 
Raymond Knopp committed
2480

2481 2482
  if (UE_flag==1) {
    printf("configuring for UE\n");
2483

2484
    set_comp_log(HW,      LOG_INFO,  LOG_HIGH, 1);
2485 2486 2487 2488 2489 2490
    set_comp_log(PHY,     LOG_INFO,   LOG_HIGH, 1);
    set_comp_log(MAC,     LOG_INFO,   LOG_HIGH, 1);
    set_comp_log(RLC,     LOG_INFO,   LOG_HIGH, 1);
    set_comp_log(PDCP,    LOG_INFO,   LOG_HIGH, 1);
    set_comp_log(OTG,     LOG_INFO,   LOG_HIGH, 1);
    set_comp_log(RRC,     LOG_INFO,   LOG_HIGH, 1);
2491
#if defined(ENABLE_ITTI)
2492
    set_comp_log(EMU,     LOG_INFO,   LOG_MED, 1);
2493
# if defined(ENABLE_USE_MME)
2494
    set_comp_log(NAS,     LOG_INFO,   LOG_HIGH, 1);
2495 2496
# endif
#endif
2497 2498
  } else {
    printf("configuring for eNB\n");
2499

2500
    set_comp_log(HW,      hw_log_level, hw_log_verbosity, 1);
2501
#ifdef OPENAIR2
2502 2503 2504 2505 2506
    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);

2507
#else
2508
    set_comp_log(PHY,     LOG_INFO,   LOG_HIGH, 1);
2509
#endif
2510 2511 2512 2513
    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);
2514
#if defined(ENABLE_ITTI)
2515
    set_comp_log(EMU,     LOG_INFO,   LOG_MED, 1);
2516
# if defined(ENABLE_USE_MME)
2517 2518 2519 2520
    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);
2521
# endif
2522
#if defined(ENABLE_SECURITY)
2523
    set_comp_log(OSA,    osa_log_level,   osa_log_verbosity, 1);
2524
#endif
2525
#endif
2526
#ifdef LOCALIZATION
2527 2528 2529 2530 2531 2532 2533 2534 2535
    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
2536
    }
2537
  }
2538

Raymond Knopp's avatar
 
Raymond Knopp committed
2539 2540
  if (ouput_vcd) {
    if (UE_flag==1)
2541
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_UE.vcd");
Raymond Knopp's avatar
 
Raymond Knopp committed
2542
    else
2543
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_eNB.vcd");
Raymond Knopp's avatar
 
Raymond Knopp committed
2544
  }
2545

2546 2547
  if (opp_enabled ==1)
    reset_opp_meas();
2548

2549
#if defined(ENABLE_ITTI)
2550

Raymond Knopp's avatar
 
Raymond Knopp committed
2551 2552
  if (UE_flag == 1) {
    log_set_instance_type (LOG_INSTANCE_UE);
2553
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
2554 2555
    log_set_instance_type (LOG_INSTANCE_ENB);
  }
2556

Raymond Knopp's avatar
 
Raymond Knopp committed
2557
  itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, itti_dump_file);
2558
#endif
2559
#ifdef OPENAIR2
2560

2561 2562
  if (opt_type != OPT_NONE) {
    radio_type_t radio_type;
2563

2564 2565
    if (frame_parms[0]->frame_type == FDD)
      radio_type = RADIO_TYPE_FDD;
2566
    else
2567
      radio_type = RADIO_TYPE_TDD;
2568

2569 2570 2571
    if (init_opt(in_path, in_ip, NULL, radio_type) == -1)
      LOG_E(OPT,"failed to run OPT \n");
  }
2572

2573
#endif
2574
#ifdef PDCP_USE_NETLINK
Raymond Knopp's avatar
 
Raymond Knopp committed
2575
  netlink_init();
2576 2577
#endif

2578
#if !defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
2579 2580 2581
  // to make a graceful exit when ctrl-c is pressed
  signal(SIGSEGV, signal_handler);
  signal(SIGINT, signal_handler);
2582
#endif
2583 2584

#ifndef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
2585 2586 2587 2588
  check_clock();
#endif

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

2592 2593 2594 2595 2596 2597 2598 2599 2600
    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
2601 2602 2603 2604 2605 2606 2607 2608
    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;
2609 2610
    init_ul_hopping(frame_parms[CC_id]);
    init_frame_parms(frame_parms[CC_id],1);
2611 2612
    //   phy_init_top(frame_parms[CC_id]);
    phy_init_lte_top(frame_parms[CC_id]);
Raymond Knopp's avatar
 
Raymond Knopp committed
2613 2614 2615
  }


2616
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2617
    //init prach for openair1 test
2618
    frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22;
Raymond Knopp's avatar
 
Raymond Knopp committed
2619
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1;
2620
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2621 2622 2623
    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
2624
    // N_ZC = (prach_fmt <4)?839:139;
Raymond Knopp's avatar
 
Raymond Knopp committed
2625
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
2626 2627

  if (UE_flag==1) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2628 2629 2630
    NB_UE_INST=1;
    NB_INST=1;

Raymond Knopp's avatar
 
Raymond Knopp committed
2631 2632
    PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE**));
    PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_UE*)*MAX_NUM_CCs);
2633 2634

    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
2635 2636 2637 2638

      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
2639
#ifndef OPENAIR2
2640 2641 2642 2643 2644 2645 2646 2647 2648

      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
2649
      }
2650

2651
#endif
2652 2653 2654


      UE[CC_id]->UE_scan = UE_scan;
2655
      UE[CC_id]->UE_scan_carrier = UE_scan_carrier;
2656 2657 2658
      UE[CC_id]->mode    = mode;

      compute_prach_seq(&UE[CC_id]->lte_frame_parms.prach_config_common,
2659 2660 2661
                        UE[CC_id]->lte_frame_parms.frame_type,
                        UE[CC_id]->X_u);

2662
      UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1234;
2663
#ifndef OPENAIR2
2664
      UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1235;
2665
#endif
2666

2667
#ifdef EXMIMO
2668

2669 2670 2671 2672
      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
2673
      }
2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692

      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
2693
      }
2694

2695
#else
2696
      UE[CC_id]->rx_total_gain_dB =  (int)rx_gain[CC_id][0];
2697
#endif
2698

2699
      UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id];
2700

2701 2702


2703
#ifdef EXMIMO
2704

Raymond Knopp's avatar
 
Raymond Knopp committed
2705
      //N_TA_offset
2706
      if (UE[CC_id]->lte_frame_parms.frame_type == TDD) {
2707 2708 2709 2710 2711 2712 2713 2714
        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
2715
      }
2716

2717
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
2718
      //already taken care of in lte-softmodem
2719
      UE[CC_id]->N_TA_offset = 0;
2720
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2721
    }
2722

Raymond Knopp's avatar
 
Raymond Knopp committed
2723 2724 2725 2726
    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;
2727 2728 2729



Raymond Knopp's avatar
 
Raymond Knopp committed
2730
    //  printf("tx_max_power = %d -> amp %d\n",tx_max_power,get_tx_amp(tx_max_power,tx_max_power));
2731 2732 2733 2734 2735 2736 2737 2738 2739
  } 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;

2740
#ifndef OPENAIR2
2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756

      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
2757

2758
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
2759

2760
      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
2761

2762
#else
2763 2764 2765
      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
2766

2767 2768 2769
      // 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
2770

2771
#endif
2772

2773
#ifdef EXMIMO
2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784

      //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
2785
      }
2786

2787 2788 2789 2790
#else
      //already taken care of in lte-softmodem
      PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 0;
#endif
2791

2792
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
2793 2794


2795 2796 2797 2798 2799 2800 2801 2802 2803
    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;

  }
2804

2805

Raymond Knopp's avatar
 
Raymond Knopp committed
2806
  dump_frame_parms(frame_parms[0]);
2807

Raymond Knopp's avatar
 
Raymond Knopp committed
2808
  if(frame_parms[0]->N_RB_DL == 100) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2809
    sample_rate = 30.72e6;
2810
    bw          = 10.0e6;
2811
#ifndef EXMIMO
2812
    openair0_cfg[0].samples_per_packet = 2048;
2813 2814 2815
    samples_per_frame = 307200; 
    openair0_cfg[card].tx_bw = 10e6;
    openair0_cfg[card].rx_bw = 10e6;
Raymond Knopp's avatar
 
Raymond Knopp committed
2816 2817
    // from usrp_time_offset
    tx_forward_nsamps = 175;
2818
    tx_delay = 8;
Raymond Knopp's avatar
 
Raymond Knopp committed
2819
#endif
2820
  } else if(frame_parms[0]->N_RB_DL == 50) {
2821
    sample_rate = 15.36e6;
2822
    bw          = 5.0e6;
2823
#ifndef EXMIMO
2824
    openair0_cfg[0].samples_per_packet = 2048;
Raymond Knopp's avatar
 
Raymond Knopp committed
2825
    samples_per_frame = 153600;
2826 2827
    openair0_cfg[card].tx_bw = 5e6;
    openair0_cfg[card].rx_bw = 5e6;
Raymond Knopp's avatar
 
Raymond Knopp committed
2828
    tx_forward_nsamps = 95;
2829
    tx_delay = 5;
Raymond Knopp's avatar
 
Raymond Knopp committed
2830
#endif
2831
  } else if (frame_parms[0]->N_RB_DL == 25) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2832
    sample_rate = 7.68e6;
2833
    bw          = 2.5e6;
2834
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
2835
    samples_per_frame = 76800;
2836 2837 2838 2839 2840 2841 2842
    openair0_cfg[card].tx_bw = 2.5e6;
    openair0_cfg[card].rx_bw = 2.5e6;
    openair0_cfg[0].samples_per_packet = 1024;
#ifdef OAI_USRP
    tx_forward_nsamps = 70;
    tx_delay = 6;
#elif OAI_BLADERF
Raymond Knopp's avatar
 
Raymond Knopp committed
2843
    tx_forward_nsamps = 70;
2844
    tx_delay = 6;
2845
#endif 
Raymond Knopp's avatar
 
Raymond Knopp committed
2846
#endif
2847
  } else if (frame_parms[0]->N_RB_DL == 6) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2848
    sample_rate = 1.92e6;
2849
    bw          = 0.96e6;
Raymond Knopp's avatar
 
Raymond Knopp committed
2850
#ifndef EXMIMO
2851
    openair0_cfg[0].samples_per_packet = 256;
Raymond Knopp's avatar
 
Raymond Knopp committed
2852
    samples_per_frame = 19200;
2853 2854
    openair0_cfg[card].tx_bw = 1.5e6;
    openair0_cfg[card].rx_bw = 1.5e6;
Raymond Knopp's avatar
 
Raymond Knopp committed
2855
    tx_forward_nsamps = 40;
2856
    tx_delay = 8;
Raymond Knopp's avatar
 
Raymond Knopp committed
2857 2858
#endif
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
2859 2860

#ifdef ETHERNET
2861

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

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

2868

2869
  for (card=0; card<MAX_CARDS; card++) {
2870
#ifndef EXMIMO
2871
    openair0_cfg[card].samples_per_packet = openair0_cfg[0].samples_per_packet;
2872 2873
#endif
    printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card,
2874 2875
           ((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
2876 2877
    openair0_cfg[card].Mod_id = 0;
#ifdef ETHERNET
2878 2879

    if (UE_flag) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2880 2881 2882
      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;
2883 2884 2885 2886
    } 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
2887
    }
2888

Raymond Knopp's avatar
 
Raymond Knopp committed
2889
#endif
2890 2891 2892
    openair0_cfg[card].sample_rate = sample_rate;
    openair0_cfg[card].tx_bw = bw;
    openair0_cfg[card].rx_bw = bw;
2893
    // in the case of the USRP, the following variables need to be initialized before the init
2894
    // since the USRP only supports one CC (for the moment), we initialize all the cards with first CC.
2895
    // in the case of EXMIMO2, these values are overwirtten in the function setup_eNB/UE_buffer
2896
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
2897 2898
    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));
2899 2900

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

2902
      openair0_cfg[card].autocal[i] = 1;
2903
      openair0_cfg[card].tx_gain[i] = tx_gain[0][i];
2904
      openair0_cfg[card].rx_gain[i] = ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->rx_total_gain_eNB_dB :
2905
                                       PHY_vars_UE_g[0][0]->rx_total_gain_dB) - USRP_GAIN_OFFSET;  // calibrated for USRP B210 @ 2.6 GHz, 30.72 MS/s
2906

2907 2908
      switch(frame_parms[0]->N_RB_DL) {
      case 6:
2909 2910 2911
        openair0_cfg[card].rx_gain[i] -= 6;
        break;

2912
      case 25:
2913 2914 2915
        openair0_cfg[card].rx_gain[i] += 6;
        break;

2916
      case 50:
2917 2918 2919
        openair0_cfg[card].rx_gain[i] += 8;
        break;

2920
      default:
2921
        break;
2922
      }
2923

2924 2925
      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];
2926
      printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n",
2927 2928 2929 2930 2931
             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
2932
    }
2933

2934
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2935
  }
2936

2937
  printf("Initializing openair0 ...");
2938
  openair0_cfg[0].log_level = glog_level;
2939

2940
  if (openair0_device_init(&openair0, &openair0_cfg[0]) <0) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2941 2942 2943
    printf("Exiting, cannot initialize device\n");
    exit(-1);
  }
2944

2945
  printf("Done\n");
2946 2947 2948

  mac_xface = malloc(sizeof(MAC_xface));

2949
#ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
2950
  int eMBMS_active=0;
2951

Raymond Knopp's avatar
 
Raymond Knopp committed
2952
  l2_init(frame_parms[0],eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL,
2953 2954 2955 2956
          0,// cba_group_active
          0); // HO flag


2957 2958
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
2959
  mac_xface->macphy_exit = &exit_fun;
2960

winckel's avatar
winckel committed
2961
#if defined(ENABLE_ITTI)
2962

Raymond Knopp's avatar
 
Raymond Knopp committed
2963
  if (create_tasks(UE_flag ? 0 : 1, UE_flag ? 1 : 0) < 0) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
2964
    printf("cannot create ITTI tasks\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2965 2966
    exit(-1); // need a softer mode
  }
2967

Raymond Knopp's avatar
 
Raymond Knopp committed
2968
  printf("ITTI tasks created\n");
winckel's avatar
winckel committed
2969
#endif
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2970 2971

#ifdef OPENAIR2
2972
  if (UE_flag==1) {
2973
    printf("Filling UE band info\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2974
    fill_ue_band_info();
2975
    mac_xface->dl_phy_sync_success (0, 0, 0, 1);
2976
  } else
2977
    mac_xface->mrbch_phy_sync_failure (0, 0, 0);
2978

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2979
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2980

2981
  /* #ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
2982 2983 2984 2985 2986 2987
  //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
2988 2989 2990 2991 2992 2993
  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
2994 2995 2996
  }
  init_predef_traffic(UE_flag ? 1 : 0, UE_flag ? 0 : 1);
  //  }
2997
  #endif */
Raymond Knopp's avatar
 
Raymond Knopp committed
2998

2999
#ifdef EXMIMO
3000
  number_of_cards = openair0_num_detected_cards;
3001 3002
#else
  number_of_cards = 1;
3003
#endif
3004

3005

3006

3007
  for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3008
    rf_map[CC_id].card=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3009
    rf_map[CC_id].chain=CC_id;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3010
  }
3011

Raymond Knopp's avatar
 
Raymond Knopp committed
3012 3013
  // connect the TX/RX buffers
  if (UE_flag==1) {
3014 3015 3016
#ifdef OAI_USRP
    openair_daq_vars.timing_advance = 160;
#else
3017
    openair_daq_vars.timing_advance = 160;
3018
#endif
3019
    if (setup_ue_buffers(UE,&openair0_cfg[0],rf_map)!=0) {
3020 3021 3022
      printf("Error setting up eNB buffer\n");
      exit(-1);
    }
3023

3024
    printf("Setting UE buffer to all-RX\n");
3025

3026
    // Set LSBs for antenna switch (ExpressMIMO)
3027
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3028
      for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++)
3029 3030
        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
3031
    }
3032

Raymond Knopp's avatar
 
Raymond Knopp committed
3033
    //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX;
3034
  } else {
3035
    openair_daq_vars.timing_advance = 0;
3036

3037 3038 3039 3040
    if (setup_eNB_buffers(PHY_vars_eNB_g[0],&openair0_cfg[0],rf_map)!=0) {
      printf("Error setting up eNB buffer\n");
      exit(-1);
    }
3041

3042
    printf("Setting eNB buffer to all-RX\n");
3043

3044
    // Set LSBs for antenna switch (ExpressMIMO)
3045
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3046
      for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++)
3047 3048
        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
3049
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3050
  }
3051

3052
#ifdef EXMIMO
3053
  openair0_config(&openair0_cfg[0],UE_flag);
Raymond Knopp's avatar
 
Raymond Knopp committed
3054 3055
#endif

3056
  /*
Raymond Knopp's avatar
 
Raymond Knopp committed
3057 3058
      for (ant=0;ant<4;ant++)
      p_exmimo_config->rf.do_autocal[ant] = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3059
  */
3060 3061

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3064 3065 3066 3067 3068 3069
  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);
3070
  else
Raymond Knopp's avatar
 
Raymond Knopp committed
3071
    printf("[OPENAIR][SCHED][INIT] Problem creating EMOS FIFO %d, error_code %d\n",CHANSOUNDER_FIFO_MINOR,error_code);
3072

3073 3074
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3075
  mlockall(MCL_CURRENT | MCL_FUTURE);
3076 3077

#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3078
  // make main thread LXRT soft realtime
3079
  /* task = */ rt_task_init_schmod(nam2num("MAIN"), 9, 0, 0, SCHED_FIFO, 0xF);
Raymond Knopp's avatar
 
Raymond Knopp committed
3080 3081 3082 3083 3084

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3087 3088
  pthread_cond_init(&sync_cond,NULL);
  pthread_mutex_init(&sync_mutex, NULL);
3089

3090
#if defined(ENABLE_ITTI)
3091

Florian Kaltenberger's avatar
Florian Kaltenberger committed
3092 3093 3094 3095 3096
  // 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);
  }
3097

3098
#endif
3099

Raymond Knopp's avatar
 
Raymond Knopp committed
3100 3101

  // this starts the DMA transfers
3102
#ifdef EXMIMO
3103

Raymond Knopp's avatar
 
Raymond Knopp committed
3104
  if (UE_flag!=1)
3105
    for (card=0; card<openair0_num_detected_cards; card++)
3106
      openair0_start_rt_acquisition(card);
3107

Raymond Knopp's avatar
 
Raymond Knopp committed
3108
#endif
3109 3110

#ifdef XFORMS
3111 3112
  int UE_id;

Raymond Knopp's avatar
 
Raymond Knopp committed
3113 3114
  if (do_forms==1) {
    fl_initialize (&argc, argv, NULL, 0, 0);
3115 3116

    if (UE_flag==0) {
3117
      form_stats_l2 = create_form_stats_form();
3118 3119 3120
      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");
3121 3122

      for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135
	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");
	  }
	}
3136
      }
3137
    } else {
3138 3139 3140 3141 3142 3143 3144
      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
3145
      if (openair_daq_vars.use_ia_receiver) {
3146 3147 3148 3149 3150
        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
3151 3152 3153
      }
    }

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

3156 3157
    if (ret == 0)
      pthread_setname_np( forms_thread, "xforms" );
3158

Raymond Knopp's avatar
 
Raymond Knopp committed
3159 3160
    printf("Scope thread created, ret=%d\n",ret);
  }
3161

3162 3163 3164
#endif

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3165 3166
  ret = pthread_create(&thread3, NULL, emos_thread, NULL);
  printf("EMOS thread created, ret=%d\n",ret);
jiangx's avatar
jiangx committed
3167 3168
  ret = pthread_create(&thread4, NULL, gps_thread, NULL);
  printf("GPS thread created, ret=%d\n",ret);
3169 3170
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3171
  rt_sleep_ns(10*FRAME_PERIOD);
3172 3173

#ifndef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3174
  pthread_attr_init (&attr_dlsch_threads);
3175
  pthread_attr_setstacksize(&attr_dlsch_threads,4*PTHREAD_STACK_MIN);
3176

3177
  pthread_attr_init (&attr_UE_thread);
3178
  pthread_attr_setstacksize(&attr_UE_thread,8192);//5*PTHREAD_STACK_MIN);
3179

3180
#ifndef LOWLATENCY
3181 3182
  sched_param_UE_thread.sched_priority = sched_get_priority_max(SCHED_FIFO);
  pthread_attr_setschedparam(&attr_UE_thread,&sched_param_UE_thread);
3183
  sched_param_dlsch.sched_priority = sched_get_priority_max(SCHED_FIFO); //OPENAIR_THREAD_PRIORITY;
Raymond Knopp's avatar
 
Raymond Knopp committed
3184 3185
  pthread_attr_setschedparam  (&attr_dlsch_threads, &sched_param_dlsch);
  pthread_attr_setschedpolicy (&attr_dlsch_threads, SCHED_FIFO);
3186
  printf("Setting eNB_thread FIFO scheduling policy with priority %d \n", sched_param_dlsch.sched_priority);
3187
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3188

3189 3190
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3191 3192
  // start the main thread
  if (UE_flag == 1) {
3193
    printf("Intializing UE Threads ...\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3194
    init_UE_threads();
3195 3196 3197 3198 3199
#ifdef DLSCH_THREAD
    init_rx_pdsch_thread();
    rt_sleep_ns(FRAME_PERIOD/10);
    init_dlsch_threads();
#endif
3200

3201
    sleep(1);
3202
#ifdef RTAI
3203
    main_ue_thread = rt_thread_create(UE_thread, NULL, 100000000);
3204
#else
3205
    error_code = pthread_create(&main_ue_thread, &attr_UE_thread, UE_thread, NULL);
3206

Raymond Knopp's avatar
 
Raymond Knopp committed
3207 3208 3209
    if (error_code!= 0) {
      LOG_D(HW,"[lte-softmodem.c] Could not allocate UE_thread, error %d\n",error_code);
      return(error_code);
3210
    } else {
3211 3212
      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
3213
    }
3214

3215
#endif
3216
    printf("UE threads created\n");
3217
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
3218 3219
    if (multi_thread>0) {
      init_eNB_proc();
3220
      sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3221 3222
      LOG_D(HW,"[lte-softmodem.c] eNB threads created\n");
    }
3223

3224
    printf("Creating main eNB_thread \n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3225
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3226
    main_eNB_thread = rt_thread_create(eNB_thread, NULL, PTHREAD_STACK_MIN);
Raymond Knopp's avatar
 
Raymond Knopp committed
3227
#else
3228
    error_code = pthread_create( &main_eNB_thread, &attr_dlsch_threads, eNB_thread, NULL );
3229

Raymond Knopp's avatar
 
Raymond Knopp committed
3230 3231 3232
    if (error_code!= 0) {
      LOG_D(HW,"[lte-softmodem.c] Could not allocate eNB_thread, error %d\n",error_code);
      return(error_code);
3233
    } else {
3234 3235
      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
3236
    }
3237

Raymond Knopp's avatar
 
Raymond Knopp committed
3238 3239
#endif
  }
3240

Raymond Knopp's avatar
 
Raymond Knopp committed
3241
  // Sleep to allow all threads to setup
Raymond Knopp's avatar
 
Raymond Knopp committed
3242
  sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3243

3244
#ifdef USE_MME
3245

3246 3247 3248
  while (start_UE == 0) {
    sleep(1);
  }
3249

3250 3251
#endif

3252
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3253
#ifndef USRP_DEBUG
Raymond Knopp's avatar
 
Raymond Knopp committed
3254
  openair0.trx_start_func(&openair0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3255
  //  printf("returning from usrp start streaming: %llu\n",get_usrp_time(&openair0));
Raymond Knopp's avatar
 
Raymond Knopp committed
3256
#endif
3257 3258
#endif

3259

Raymond Knopp's avatar
 
Raymond Knopp committed
3260
  pthread_mutex_lock(&sync_mutex);
3261
  sync_var=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3262 3263
  pthread_cond_broadcast(&sync_cond);
  pthread_mutex_unlock(&sync_mutex);
3264

Raymond Knopp's avatar
 
Raymond Knopp committed
3265 3266 3267
  // wait for end of program
  printf("TYPE <CTRL-C> TO TERMINATE\n");
  //getchar();
3268 3269

#if defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
3270 3271
  printf("Entering ITTI signals handler\n");
  itti_wait_tasks_end();
3272
  oai_exit=1;
3273
#else
3274

Raymond Knopp's avatar
 
Raymond Knopp committed
3275 3276
  while (oai_exit==0)
    rt_sleep_ns(FRAME_PERIOD);
3277

3278
#endif
3279

Raymond Knopp's avatar
 
Raymond Knopp committed
3280
  // stop threads
3281
#ifdef XFORMS
Raymond Knopp's avatar
 
Raymond Knopp committed
3282
  printf("waiting for XFORMS thread\n");
3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296

  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++) {
3297 3298 3299 3300
	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
3301
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
3302
    }
3303 3304
  }

3305 3306
#endif

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3309 3310
  // cleanup
  if (UE_flag == 1) {
3311
#ifdef EXMIMO
3312
#ifdef RTAI
3313
    rt_thread_join(main_ue_thread);
3314
#else
3315
    pthread_join(main_ue_thread,&status);
3316 3317
#endif
#ifdef DLSCH_THREAD
Raymond Knopp's avatar
 
Raymond Knopp committed
3318 3319
    cleanup_dlsch_threads();
    cleanup_rx_pdsch_thread();
3320
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3321
#endif
3322
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
3323
#ifdef DEBUG_THREADS
Raymond Knopp's avatar
 
Raymond Knopp committed
3324
    printf("Joining eNB_thread ...");
Raymond Knopp's avatar
 
Raymond Knopp committed
3325
#endif
3326
#ifdef RTAI
3327
    rt_thread_join(main_eNB_thread);
3328
#else
3329 3330
    int *eNB_thread_status_p;
    int result = pthread_join( main_eNB_thread, (void**)&eNB_thread_status_p );
Raymond Knopp's avatar
 
Raymond Knopp committed
3331
#ifdef DEBUG_THREADS
3332

3333
    if (result != 0) {
3334
      printf( "\nError joining main_eNB_thread.\n" );
3335
    } else {
3336 3337 3338 3339 3340
      if (eNB_thread_status_p) {
        printf( "status %d\n", *eNB_thread_status_p );
      } else {
        printf( "The thread was killed. No status available.\n");
      }
3341
    }
3342

3343 3344
#else
    UNUSED(result);
3345 3346
#endif // DEBUG_THREADS
#endif // RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3347

Raymond Knopp's avatar
 
Raymond Knopp committed
3348 3349 3350
    if (multi_thread>0) {
      printf("Killing eNB processing threads\n");
      kill_eNB_proc();
Raymond Knopp's avatar
 
Raymond Knopp committed
3351

Raymond Knopp's avatar
 
Raymond Knopp committed
3352
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3353
  }
3354

3355
#ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
3356
  //cleanup_pdcp_thread();
3357 3358
#endif

3359
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3360
  stop_rt_timer();
3361
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3362 3363
  pthread_cond_destroy(&sync_cond);
  pthread_mutex_destroy(&sync_mutex);
3364

3365

3366
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3367
  printf("stopping card\n");
3368
  openair0_stop(0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3369 3370
  printf("closing openair0_lib\n");
  openair0_close();
Raymond Knopp's avatar
 
Raymond Knopp committed
3371
#endif
3372 3373

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3374 3375 3376
  printf("waiting for EMOS thread\n");
  pthread_cancel(thread3);
  pthread_join(thread3,&status);
jiangx's avatar
jiangx committed
3377 3378 3379
  printf("waiting for GPS thread\n");
  pthread_cancel(thread4);
  pthread_join(thread4,&status);
3380 3381 3382
#endif

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3383 3384
  error_code = rtf_destroy(CHANSOUNDER_FIFO_MINOR);
  printf("[OPENAIR][SCHED][CLEANUP] EMOS FIFO closed, error_code %d\n", error_code);
3385 3386
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3387
  if (ouput_vcd)
3388
    VCD_SIGNAL_DUMPER_CLOSE();
3389

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3390
#ifdef OPENAIR2
3391

3392
  if (opt_enabled == 1)
3393
    terminate_opt();
3394

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3395
#endif
3396

Raymond Knopp's avatar
 
Raymond Knopp committed
3397
  logClean();
3398

Raymond Knopp's avatar
 
Raymond Knopp committed
3399 3400
  return 0;
}
3401 3402


3403 3404 3405
/* 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
3406
   antennas are mapped to successive RF chains on the same card. */
3407 3408
int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs])
{
3409

3410
  int i, CC_id;
3411
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3412
  uint16_t N_TA_offset = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3413 3414
#else
  int j;
Raymond Knopp's avatar
 
Raymond Knopp committed
3415
#endif
3416
  LTE_DL_FRAME_PARMS *frame_parms;
3417

Raymond Knopp's avatar
 
Raymond Knopp committed
3418

3419 3420
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    if (phy_vars_eNB[CC_id]) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3421 3422
      frame_parms = &(phy_vars_eNB[CC_id]->lte_frame_parms);
      printf("setup_eNB_buffers: frame_parms = %p\n",frame_parms);
3423
    } else {
3424 3425
      printf("phy_vars_eNB[%d] not initialized\n", CC_id);
      return(-1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3426
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3427

3428
#ifndef EXMIMO
3429

3430 3431
    if (frame_parms->frame_type == TDD) {
      if (frame_parms->N_RB_DL == 100)
3432
        N_TA_offset = 624;
3433
      else if (frame_parms->N_RB_DL == 50)
3434
        N_TA_offset = 624/2;
3435
      else if (frame_parms->N_RB_DL == 25)
3436
        N_TA_offset = 624/4;
Raymond Knopp's avatar
 
Raymond Knopp committed
3437
    }
3438

Raymond Knopp's avatar
 
Raymond Knopp committed
3439
#endif
3440 3441


3442 3443 3444



Raymond Knopp's avatar
 
Raymond Knopp committed
3445
    // replace RX signal buffers with mmaped HW versions
3446
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3447 3448 3449
    openair0_cfg[CC_id].tx_num_channels = 0;
    openair0_cfg[CC_id].rx_num_channels = 0;

3450
    for (i=0; i<frame_parms->nb_antennas_rx; i++) {
3451 3452 3453
      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];
3454

3455
      if (openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i]) {
3456 3457 3458 3459 3460 3461
        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++;
3462
      }
3463

3464
      printf("rxdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]);
3465 3466 3467 3468

      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;
3469
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
3470
    }
3471 3472

    for (i=0; i<frame_parms->nb_antennas_tx; i++) {
3473 3474 3475
      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];
3476

3477
      if (openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i]) {
3478 3479 3480 3481 3482 3483
        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++;
3484
      }
3485

3486
      printf("txdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3487 3488 3489 3490

      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;
3491
      }
3492
    }
3493

3494
#else // not EXMIMO
3495 3496 3497
    rxdata = (int32_t**)malloc16(frame_parms->nb_antennas_rx*sizeof(int32_t*));
    txdata = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*));

3498
    for (i=0; i<frame_parms->nb_antennas_rx; i++) {
3499
      free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]);
3500 3501
      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
3502 3503
      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
3504
    }
3505 3506

    for (i=0; i<frame_parms->nb_antennas_tx; i++) {
3507
      free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3508
      txdata[i] = (int32_t*)(16 + malloc16(16 + samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation
3509 3510
      phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i] = txdata[i];
      memset(txdata[i], 0, samples_per_frame*sizeof(int32_t));
3511
      printf("txdata[%d] @ %p\n", i, phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3512

Raymond Knopp's avatar
 
Raymond Knopp committed
3513
    }
3514

Raymond Knopp's avatar
 
Raymond Knopp committed
3515
#endif
3516
  }
3517

3518
  return(0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3519
}
3520

3521 3522
void reset_opp_meas(void)
{
3523 3524 3525
  int sfn;
  reset_meas(&softmodem_stats_mt);
  reset_meas(&softmodem_stats_hw);
3526

3527 3528 3529 3530 3531 3532
  for (sfn=0; sfn < 10; sfn++) {
    reset_meas(&softmodem_stats_tx_sf[sfn]);
    reset_meas(&softmodem_stats_rx_sf[sfn]);
  }
}

3533 3534
void print_opp_meas(void)
{
3535 3536 3537
  int sfn=0;
  print_meas(&softmodem_stats_mt, "Main ENB Thread", NULL, NULL);
  print_meas(&softmodem_stats_hw, "HW Acquisation", NULL, NULL);
3538

3539 3540 3541 3542 3543
  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);
  }
}