"openair2/LAYER2/MAC/defs_nb_iot.h" did not exist on "e6c25ec9eafbc85bc479329bb4f3368e7ec54466"
lte-softmodem.c 107 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 250 251 252
int UE_scan = 1;
runmode_t mode = normal_txrx;


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

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

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

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

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

#endif
298 299

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
321

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

Raymond Knopp's avatar
 
Raymond Knopp committed
330

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
359 360 361

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

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

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

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

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


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

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

404 405 406 407
    // print out all the frames to stderr
    fprintf(stderr, "Error: signal %d:\n", sig);
    backtrace_symbols_fd(array, size, 2);
    exit(-1);
408 409
  } else {
    printf("trying to exit gracefully...\n");
410
    oai_exit = 1;
411 412
  }
}
413
#endif
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451
#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");
  printf("  --debug-ue-prach \n");
  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");

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

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

  oai_exit = 1;

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

  //rt_sleep_ns(FRAME_PERIOD);

  //exit (-1);
}

Raymond Knopp's avatar
 
Raymond Knopp committed
472 473
static int latency_target_fd = -1;
static int32_t latency_target_value = 0;
474
/* Latency trick - taken from cyclictest.c
Raymond Knopp's avatar
 
Raymond Knopp committed
475 476 477 478 479 480 481 482 483
 * 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
484 485 486 487
static void set_latency_target(void)
{
  struct stat s;
  int ret;
488

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

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

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

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

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

507
#ifdef XFORMS
508

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

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

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

      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;
531
      }
532
    }
533

534 535 536
    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;
537 538 539
  }
}

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

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

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

555
# ifdef ENABLE_XFORMS_WRITE_STATS
556 557

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

562
#endif
563

Raymond Knopp's avatar
 
Raymond Knopp committed
564 565
  while (!oai_exit) {
    if (UE_flag==1) {
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
566
      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
567
      fl_set_object_label(form_stats->stats_text, stats_buffer);
568

569 570 571 572 573
      phy_scope_UE(form_ue[0],
                   PHY_vars_UE_g[0][0],
                   0,
                   0,7);

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

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

584 585
      fl_set_object_label(form_stats->stats_text, stats_buffer);

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

594
    }
595

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

  printf("%s",stats_buffer);
602

603
# ifdef ENABLE_XFORMS_WRITE_STATS
604

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

619
# endif
620

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

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

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

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

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

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

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

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

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

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

668 669 670

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

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

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

  pthread_exit((void*) arg);

}

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

jiangx's avatar
jiangx committed
710
  int channel_buffer_size,ret;
711

712 713 714
  time_t timer;
  struct tm *now;

715
  struct sched_param sched_param;
716 717

  sched_param.sched_priority = sched_get_priority_max(SCHED_FIFO)-1;
718
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
719

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

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

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

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


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

  dumpfile_id = fopen(dumpfile_name,"w");
752 753 754 755 756

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


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

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

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

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

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

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

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

814 815 816
  free(fifo2file_buffer);
  fclose(dumpfile_id);
  close(fifo);
817

818 819 820 821 822
  pthread_exit((void*) arg);

}
#endif

823 824


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

841 842 843 844 845
    LOG_D(EMU,"\n");
  }
}
#endif

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

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
854

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

864 865 866
      itti_receive_msg (TASK_L2L1, &message_p);

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

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

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
920
  return NULL;
921 922 923
}
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
924

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

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

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
942

Raymond Knopp's avatar
 
Raymond Knopp committed
943
    for (aa=0; aa<phy_vars_eNB->lte_frame_parms.nb_antennas_tx; aa++) {
944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965
      if (phy_vars_eNB->lte_frame_parms.Ncp == EXTENDED) {
        PHY_ofdm_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F],
                     dummy_tx_b,
                     phy_vars_eNB->lte_frame_parms.log2_symbol_size,
                     6,
                     phy_vars_eNB->lte_frame_parms.nb_prefix_samples,
                     CYCLIC_PREFIX);
        PHY_ofdm_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F+slot_sizeF],
                     dummy_tx_b+(phy_vars_eNB->lte_frame_parms.samples_per_tti>>1),
                     phy_vars_eNB->lte_frame_parms.log2_symbol_size,
                     6,
                     phy_vars_eNB->lte_frame_parms.nb_prefix_samples,
                     CYCLIC_PREFIX);
      } else {
        normal_prefix_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F],
                          dummy_tx_b,
                          7,
                          &(phy_vars_eNB->lte_frame_parms));
        normal_prefix_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F+slot_sizeF],
                          dummy_tx_b+(phy_vars_eNB->lte_frame_parms.samples_per_tti>>1),
                          7,
                          &(phy_vars_eNB->lte_frame_parms));
Raymond Knopp's avatar
 
Raymond Knopp committed
966
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
967 968

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


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

  eNB_proc_t *proc = (eNB_proc_t*)param;
1006 1007 1008 1009 1010 1011
  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");
  }
1012 1013 1014
  // set default return value
  eNB_thread_tx_status[proc->subframe] = 0;

Raymond Knopp's avatar
 
Raymond Knopp committed
1015 1016
#ifdef RTAI
  RT_TASK *task;
1017
  char task_name[8];
Raymond Knopp's avatar
 
Raymond Knopp committed
1018

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

1022 1023 1024
  if (task == NULL) {
    LOG_E(PHY,"[SCHED][eNB] Problem starting eNB_proc_TX thread_index %d (%s)!!!!\n",proc->subframe,task_name);
    return 0;
1025 1026 1027 1028 1029
  } else {
    LOG_I(PHY,"[SCHED][eNB] eNB TX thread CC %d SF %d started with id %p\n",
          proc->CC_id,
          proc->subframe,
          task);
1030
  }
1031

Raymond Knopp's avatar
 
Raymond Knopp committed
1032
#else
1033
#ifdef LOWLATENCY
1034 1035 1036
  struct sched_attr attr;
  unsigned int flags = 0;

1037 1038 1039 1040
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1041

1042 1043 1044
  // 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
1045 1046
  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
1047

1048 1049 1050 1051
  if (sched_setattr(0, &attr, flags) < 0 ) {
    perror("[SCHED] eNB tx thread: sched_setattr failed\n");
    return &eNB_thread_tx_status[proc->subframe];
  }
1052

1053
  LOG_I( HW, "[SCHED] eNB TX deadline thread %d(tid %ld) started on CPU %d\n", proc->subframe, gettid(), sched_getcpu() );
1054
#else
1055
  LOG_I( HW, "[SCHED][eNB] TX thread %d started on CPU %d TID %d\n", proc->subframe, sched_getcpu(),gettid() );
1056 1057
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
1058 1059 1060 1061 1062 1063 1064 1065
#endif

  mlockall(MCL_CURRENT | MCL_FUTURE);

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

1066
  while (!oai_exit) {
1067

1068
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe), 0 );
1069

1070
    if (pthread_mutex_lock(&proc->mutex_tx) != 0) {
1071
      LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc %d\n", proc->subframe );
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1072
      exit_fun("nothing to add");
1073
      break;
1074
    }
1075

1076
    while (proc->instance_cnt_tx < 0) {
1077 1078 1079
      // 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
1080
    }
1081

1082 1083 1084 1085 1086
    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
1087

1088 1089
    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 );
1090 1091 1092
    start_meas( &softmodem_stats_tx_sf[proc->subframe] );

    if (oai_exit) break;
1093

1094 1095 1096
    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))||
         (PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == FDD))) {
ghaddab's avatar
ghaddab committed
1097

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

1100
    }
1101

1102 1103 1104
    if ((subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_tx) == SF_S)) {
      phy_procedures_eNB_TX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay, NULL );
    }
1105

1106
    do_OFDM_mod_rt( proc->subframe_tx, PHY_vars_eNB_g[0][proc->CC_id] );
1107

1108 1109 1110 1111 1112
    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
1113

1114 1115 1116 1117 1118 1119 1120 1121 1122
    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++;
1123

1124 1125 1126
    if (proc->frame_tx==1024)
      proc->frame_tx=0;

1127 1128 1129
    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);

1130 1131 1132
  }

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1135 1136 1137
#ifdef HARD_RT
  rt_make_soft_real_time();
#endif
1138

Raymond Knopp's avatar
 
Raymond Knopp committed
1139
#ifdef DEBUG_THREADS
1140
  printf( "Exiting eNB thread TX %d\n", proc->subframe );
Raymond Knopp's avatar
 
Raymond Knopp committed
1141 1142 1143 1144 1145
#endif
  // clean task
#ifdef RTAI
  rt_task_delete(task);
#endif
1146

1147 1148
  eNB_thread_tx_status[proc->subframe] = 0;
  return &eNB_thread_tx_status[proc->subframe];
Raymond Knopp's avatar
 
Raymond Knopp committed
1149 1150 1151
}


1152 1153 1154 1155 1156 1157 1158 1159 1160 1161
/*!
 * \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
1162
  eNB_proc_t *proc = (eNB_proc_t*)param;
1163

1164 1165 1166 1167 1168 1169
  FILE  *rx_time_file;
  char rx_time_name[101];
  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");
  }
1170 1171 1172
  // set default return value
  eNB_thread_rx_status[proc->subframe] = 0;

Raymond Knopp's avatar
 
Raymond Knopp committed
1173 1174
#ifdef RTAI
  RT_TASK *task;
1175
  char task_name[8];
Raymond Knopp's avatar
 
Raymond Knopp committed
1176

1177
  sprintf(task_name,"RXC%1dS%1d",proc->CC_id,proc->subframe);
Raymond Knopp's avatar
 
Raymond Knopp committed
1178 1179 1180
  task = rt_task_init_schmod(nam2num(task_name), 0, 0, 0, SCHED_FIFO, 0xF);

  if (task==NULL) {
1181 1182
    LOG_E(PHY,"[SCHED][eNB] Problem starting eNB_proc_RX thread_index %d (%s)!!!!\n",proc->subframe,task_name);
    return 0;
1183
  } else {
1184
    LOG_I(PHY,"[SCHED][eNB] eNB RX thread CC_id %d SF %d started with id %p\n", /*  on CPU %d*/
1185 1186 1187
          proc->CC_id,
          proc->subframe,
          task); /*,rtai_cpuid()*/
Raymond Knopp's avatar
 
Raymond Knopp committed
1188
  }
1189

Raymond Knopp's avatar
 
Raymond Knopp committed
1190
#else
1191
#ifdef LOWLATENCY
1192 1193 1194
  struct sched_attr attr;
  unsigned int flags = 0;

1195 1196 1197 1198
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1199

Navid Nikaein's avatar
Navid Nikaein committed
1200
  /* This creates a 2ms reservation every 10ms period*/
1201
  attr.sched_policy = SCHED_DEADLINE;
1202
  attr.sched_runtime  = 0.9 *  1000000; // each rx thread must finish its job in the worst case in 2ms
1203
  attr.sched_deadline = 2   *  1000000; // each rx thread will finish within 2ms
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1204
  attr.sched_period   = 1   * 10000000; // each rx thread has a period of 10ms from the starting point
1205 1206

  if (sched_setattr(0, &attr, flags) < 0 ) {
1207
    perror("[SCHED] eNB RX sched_setattr failed\n");
1208
    return &eNB_thread_rx_status[proc->subframe];
1209
  }
1210

1211
  LOG_I( HW, "[SCHED] eNB RX deadline thread %d(id %ld) started on CPU %d\n", proc->subframe, gettid(), sched_getcpu() );
1212
#else
1213
  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
1214
#endif
1215
#endif // RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
1216 1217 1218 1219 1220 1221 1222

  mlockall(MCL_CURRENT | MCL_FUTURE);

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

1223
  while (!oai_exit) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1224

1225
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 0 );
1226

Raymond Knopp's avatar
 
Raymond Knopp committed
1227
    if (pthread_mutex_lock(&proc->mutex_rx) != 0) {
1228 1229 1230
      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
1231 1232
    }

1233
    while (proc->instance_cnt_rx < 0) {
1234 1235 1236
      // 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
1237
    }
1238 1239 1240 1241 1242 1243 1244

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

1245 1246
    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 );
1247
    start_meas( &softmodem_stats_rx_sf[proc->subframe] );
1248

Raymond Knopp's avatar
 
Raymond Knopp committed
1249
    if (oai_exit) break;
1250

Raymond Knopp's avatar
 
Raymond Knopp committed
1251
    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)) ||
1252
         (PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == FDD))) {
1253
      phy_procedures_eNB_RX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay );
Raymond Knopp's avatar
 
Raymond Knopp committed
1254
    }
1255 1256

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1260
    if (pthread_mutex_lock(&proc->mutex_rx) != 0) {
1261 1262 1263
      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
1264
    }
1265 1266 1267 1268 1269 1270 1271

    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
1272
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1273 1274

    proc->frame_rx++;
1275

Raymond Knopp's avatar
 
Raymond Knopp committed
1276 1277
    if (proc->frame_rx==1024)
      proc->frame_rx=0;
1278

1279 1280 1281
    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
1282
  }
1283 1284

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1287
#ifdef HARD_RT
Raymond Knopp's avatar
 
Raymond Knopp committed
1288 1289 1290 1291
  rt_make_soft_real_time();
#endif

#ifdef DEBUG_THREADS
1292
  printf( "Exiting eNB thread RX %d\n", proc->subframe );
Raymond Knopp's avatar
 
Raymond Knopp committed
1293 1294 1295 1296
#endif
  // clean task
#ifdef RTAI
  rt_task_delete(task);
Raymond Knopp's avatar
 
Raymond Knopp committed
1297 1298
#endif

1299 1300
  eNB_thread_rx_status[proc->subframe] = 0;
  return &eNB_thread_rx_status[proc->subframe];
Raymond Knopp's avatar
 
Raymond Knopp committed
1301 1302 1303 1304
}



Raymond Knopp's avatar
 
Raymond Knopp committed
1305

1306 1307
void init_eNB_proc(void)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1308
  int i;
Raymond Knopp's avatar
 
Raymond Knopp committed
1309 1310
  int CC_id;

1311 1312 1313 1314
  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] );
1315

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

1319
      pthread_attr_init( &attr_eNB_proc_rx[CC_id][i] );
1320

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

1324
#ifndef LOWLATENCY
1325
      // set the kernel scheduling policy and priority
Raymond Knopp's avatar
 
Raymond Knopp committed
1326 1327 1328 1329 1330 1331
      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);
1332
      printf("Setting OS scheduler to SCHED_FIFO for eNB [cc%d][thread%d] \n",CC_id, i);
1333 1334
#endif

1335 1336 1337
      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
1338
      PHY_vars_eNB_g[0][CC_id]->proc[i].CC_id = CC_id;
1339 1340 1341 1342 1343 1344
      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] );
1345 1346 1347 1348 1349
      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
1350 1351
      PHY_vars_eNB_g[0][CC_id]->proc[i].frame_tx = 0;
      PHY_vars_eNB_g[0][CC_id]->proc[i].frame_rx = 0;
1352
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
1353 1354
      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
1355
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
1356 1357
      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
1358
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1359
    }
1360 1361


1362
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
1363 1364
    // 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
1365

Raymond Knopp's avatar
 
Raymond Knopp committed
1366
    //PHY_vars_eNB_g[0][CC_id]->proc[0].frame_rx = 1023;
Raymond Knopp's avatar
 
Raymond Knopp committed
1367 1368
    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
1369
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
1370 1371
    // 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
1372
    //    PHY_vars_eNB_g[0][CC_id]->proc[7].frame_tx = 1;
Raymond Knopp's avatar
 
Raymond Knopp committed
1373 1374
    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
1375
    //    PHY_vars_eNB_g[0][CC_id]->proc[0].frame_tx = 1;
Raymond Knopp's avatar
 
Raymond Knopp committed
1376
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1377 1378
  }
}
Raymond Knopp's avatar
 
Raymond Knopp committed
1379

1380 1381 1382 1383 1384 1385
/*!
 * \brief Terminate eNB TX and RX threads.
 */
void kill_eNB_proc(void)
{
  int *status;
Raymond Knopp's avatar
 
Raymond Knopp committed
1386

1387 1388
  for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++)
    for (int i=0; i<NUM_ENB_THREADS; i++) {
1389

Raymond Knopp's avatar
 
Raymond Knopp committed
1390
#ifdef DEBUG_THREADS
1391
      printf( "Killing TX CC_id %d thread %d\n", CC_id, i );
Raymond Knopp's avatar
 
Raymond Knopp committed
1392
#endif
1393 1394 1395 1396

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1402
#ifdef DEBUG_THREADS
1403

1404 1405 1406 1407 1408 1409 1410 1411 1412
      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" );
        }
      }
1413

1414 1415
#else
      UNUSED(result)
Raymond Knopp's avatar
 
Raymond Knopp committed
1416
#endif
1417

Raymond Knopp's avatar
 
Raymond Knopp committed
1418
#ifdef DEBUG_THREADS
1419
      printf( "Killing RX CC_id %d thread %d\n", CC_id, i );
Raymond Knopp's avatar
 
Raymond Knopp committed
1420
#endif
1421 1422 1423 1424

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

1430 1431
#ifdef DEBUG_THREADS

1432 1433 1434 1435 1436 1437 1438 1439 1440
      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" );
        }
      }
1441

1442 1443
#else
      UNUSED(result)
Raymond Knopp's avatar
 
Raymond Knopp committed
1444
#endif
1445 1446 1447 1448 1449

      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
1450
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1451 1452 1453
}


Raymond Knopp's avatar
 
Raymond Knopp committed
1454 1455


1456

Raymond Knopp's avatar
 
Raymond Knopp committed
1457

1458 1459 1460 1461 1462 1463
/*!
 * \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 )
1464
{
1465 1466
  UNUSED(arg);
  static int eNB_thread_status;
1467

1468
  unsigned char slot;
1469
#ifdef EXMIMO
1470
  slot=0;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1471
  RTIME time_in;
Raymond Knopp's avatar
 
Raymond Knopp committed
1472
  volatile unsigned int *DAQ_MBOX = openair0_daq_cnt();
Raymond Knopp's avatar
 
Raymond Knopp committed
1473 1474
  int mbox_target=0,mbox_current=0;
  int hw_slot,delay_cnt;
Raymond Knopp's avatar
 
Raymond Knopp committed
1475 1476
  int diff;
  int ret;
1477
  int first_run=1;
Raymond Knopp's avatar
 
Raymond Knopp committed
1478
#else
1479 1480 1481
  // the USRP implementation operates on subframes, not slots
  // one subframe consists of one even and one odd slot
  slot = 1;
1482
  int spp;
1483
  int tx_launched = 0;
1484 1485 1486

  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
1487

1488
  int hw_subframe = 0; // 0..NUM_ENB_THREADS-1 => 0..9
1489
  spp = openair0_cfg[0].samples_per_packet;
1490 1491
  unsigned int rx_pos = 0;
  unsigned int tx_pos = spp*tx_delay;
Raymond Knopp's avatar
 
Raymond Knopp committed
1492
#endif
1493
  int CC_id=0;	
1494
  struct timespec trx_time0, trx_time1, trx_time2;
1495

1496
#ifdef RTAI
1497
  RT_TASK* task = rt_task_init_schmod(nam2num("eNBmain"), 0, 0, 0, SCHED_FIFO, 0xF);
1498
#else
1499
#ifdef LOWLATENCY
1500 1501 1502
  struct sched_attr attr;
  unsigned int flags = 0;

Raymond Knopp's avatar
 
Raymond Knopp committed
1503 1504 1505 1506
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1507

Raymond Knopp's avatar
 
Raymond Knopp committed
1508 1509
  /* This creates a .5 ms  reservation */
  attr.sched_policy = SCHED_DEADLINE;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1510
  attr.sched_runtime  = 0.1 * 1000000;
Raymond Knopp's avatar
 
Raymond Knopp committed
1511
  attr.sched_deadline = 0.5 * 1000000;
1512 1513
  attr.sched_period   = 1.0 * 1000000;

Lionel Gauthier's avatar
Lionel Gauthier committed
1514

Raymond Knopp's avatar
 
Raymond Knopp committed
1515 1516 1517 1518
  /* 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");
     }*/
1519

1520
  if (sched_setattr(0, &attr, flags) < 0 ) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1521 1522 1523 1524
    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",
1525
          gettid(),sched_getcpu());
Raymond Knopp's avatar
 
Raymond Knopp committed
1526
  }
1527

1528
#endif
1529 1530
#endif

1531 1532 1533 1534 1535
  // stop early, if an exit is requested
  // FIXME really neccessary?
  if (oai_exit)
    goto eNB_thread_cleanup;

1536
#ifdef RTAI
1537
  printf( "[SCHED][eNB] Started eNB main thread (id %p)\n", task );
Raymond Knopp's avatar
 
Raymond Knopp committed
1538
#else
1539
  printf( "[SCHED][eNB] Started eNB main thread on CPU %d TID %d\n", sched_getcpu(), gettid());
1540 1541 1542
#endif

#ifdef HARD_RT
1543
  rt_make_hard_real_time();
1544 1545
#endif

1546 1547 1548 1549 1550 1551 1552 1553
  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;
1554

1555 1556
  printf( "waiting for sync (eNB_thread)\n" );
  pthread_mutex_lock( &sync_mutex );
1557

1558 1559
  while (sync_var<0)
    pthread_cond_wait( &sync_cond, &sync_mutex );
1560

1561
  pthread_mutex_unlock(&sync_mutex);
1562

1563
  int frame = 0;
1564

1565 1566
  while (!oai_exit) {
    start_meas( &softmodem_stats_mt );
Raymond Knopp's avatar
 
Raymond Knopp committed
1567

1568
#ifdef EXMIMO
1569 1570
    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]);
1571 1572
    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);
1573 1574 1575 1576
    //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];
1577

1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588
    //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;
1589

1590 1591
      if (diff<0)
        diff = diff +150;
1592

1593 1594 1595 1596
      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)))) {
1597

1598 1599 1600 1601
      // 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);
      
1602
      if (exit_missed_slots==1) {
1603 1604
        stop_meas(&softmodem_stats_mt);
        exit_fun("[HW][eNB] missed slot");
1605
      } else {
1606
        num_missed_slots++;
1607
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_MISSED_SLOTS_ENB,num_missed_slots );
1608
      }
1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630

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

    
1631
    }
1632

1633
    if (diff>8)
1634 1635
      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);
1636

1637 1638
    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);
1639 1640

    delay_cnt = 0;
1641

1642 1643 1644 1645
    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);
1646
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP,1);
1647
      ret = rt_sleep_ns(diff*DAQ_PERIOD);
1648 1649
      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);
1650

1651 1652
      if (ret)
        LOG_D(HW,"eNB Frame %d, time %llu: rt_sleep_ns returned %d\n",frame, time_in);
1653

Raymond Knopp's avatar
 
Raymond Knopp committed
1654
      hw_slot = (((((volatile unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15;
1655 1656 1657
      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());
1658
      delay_cnt++;
1659

1660 1661 1662 1663 1664
      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");
      }
1665

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1668
      if ((mbox_current>=135) && (mbox_target<15)) //handle the frame wrap-arround
1669
        diff = 150-mbox_current+mbox_target;
Raymond Knopp's avatar
 
Raymond Knopp committed
1670
      else if ((mbox_current<15) && (mbox_target>=135))
1671
        diff = -150+mbox_target-mbox_current;
Raymond Knopp's avatar
 
Raymond Knopp committed
1672
      else
1673 1674
        diff = mbox_target - mbox_current;
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1675

1676
#else  // EXMIMO
1677 1678
    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 );
1679
    tx_launched = 0;
1680

1681
    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
1682

1683
      unsigned int rxs;
Raymond Knopp's avatar
 
Raymond Knopp committed
1684
#ifndef USRP_DEBUG
1685 1686 1687
      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
1688

1689
      clock_gettime( CLOCK_MONOTONIC, &trx_time0 );
1690

1691 1692 1693
      // 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];
1694

1695
      start_meas( &softmodem_stats_hw );
1696

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

1706 1707
      if (rxs != spp)
        exit_fun( "problem receiving samples" );
Raymond Knopp's avatar
 
Raymond Knopp committed
1708

1709
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
1710

1711
      // Transmit TX buffer based on timestamp from RX
1712
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723

      // 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,
1724
                                1);
Raymond Knopp's avatar
 
Raymond Knopp committed
1725 1726
      }

1727 1728
      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 );
1729 1730 1731 1732

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

1733
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE,0);
1734 1735 1736 1737 1738 1739 1740 1741
#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;
1742

1743
        for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778
          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
1779 1780

#endif // USRP
1781

1782
    if (oai_exit) break;
Raymond Knopp's avatar
 
Raymond Knopp committed
1783

1784 1785 1786 1787 1788
    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;
1789

1790 1791
      if (time_diff < timing_info.time_min)
        timing_info.time_min = time_diff;
1792

1793 1794
      if (time_diff > timing_info.time_max)
        timing_info.time_max = time_diff;
1795

1796 1797 1798 1799 1800 1801
      timing_info.time_avg += time_diff;
    }

    timing_info.n_samples++;

    if ((slot&1) == 1) {
1802
      // odd slot
1803
#ifdef EXMIMO
1804
      int sf = ((slot>>1)+1)%10;
Raymond Knopp's avatar
 
Raymond Knopp committed
1805
#else
1806
      int sf = hw_subframe;
Raymond Knopp's avatar
 
Raymond Knopp committed
1807
#endif
1808 1809

      for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1810 1811
#ifdef EXMIMO

1812 1813
        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);
1814 1815
        } 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);
1816 1817
          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);
1818

1819 1820 1821 1822
          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);
            }
1823
          } else {
1824 1825 1826 1827
            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");
          }
        }
1828

Raymond Knopp's avatar
 
Raymond Knopp committed
1829 1830
#endif

1831 1832 1833 1834 1835
        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
1836

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

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

1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852
        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
1853
      }
1854 1855 1856 1857
    }

#ifdef EXMIMO
    slot++;
1858

1859 1860 1861 1862
    if (slot == 20) {
      frame++;
      slot = 0;
    }
1863

Raymond Knopp's avatar
 
Raymond Knopp committed
1864
#else
1865 1866
    hw_subframe++;
    slot += 2;
1867

1868
    if (hw_subframe == NUM_ENB_THREADS) {
1869
      // the radio frame is complete, start over
1870 1871 1872 1873
      hw_subframe = 0;
      frame++;
      slot = 1;
    }
1874 1875

#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1876

1877
#if defined(ENABLE_ITTI)
1878
    itti_update_lte_time( frame, slot );
1879
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1880
  }
1881 1882

eNB_thread_cleanup:
Raymond Knopp's avatar
 
Raymond Knopp committed
1883
#ifdef DEBUG_THREADS
1884
  printf( "eNB_thread: finished, ran %d times.\n", frame );
Raymond Knopp's avatar
 
Raymond Knopp committed
1885
#endif
1886

1887
#ifdef HARD_RT
Raymond Knopp's avatar
 
Raymond Knopp committed
1888
  rt_make_soft_real_time();
1889 1890
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
1891
#ifdef DEBUG_THREADS
1892
  printf( "Exiting eNB_thread ..." );
Raymond Knopp's avatar
 
Raymond Knopp committed
1893 1894
#endif
  // clean task
1895
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
1896
  rt_task_delete(task);
1897
#endif
1898 1899 1900

  eNB_thread_status = 0;
  return &eNB_thread_status;
Raymond Knopp's avatar
 
Raymond Knopp committed
1901
}
1902

1903

Raymond Knopp's avatar
 
Raymond Knopp committed
1904

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1905

1906 1907
static void get_options (int argc, char **argv)
{
1908 1909 1910
  int c;
  //  char                          line[1000];
  //  int                           l;
1911
  int k,i;//,j,k;
1912
#if defined(OAI_USRP) || defined(CPRIGW)
1913
  int clock_src;
1914
#endif
1915 1916 1917 1918 1919
  int CC_id;
#ifdef EXMIMO
  char rxg_fname[256], line[1000];
  FILE *rxg_fd;
  int l;
1920
#endif
1921 1922 1923



1924 1925

  const Enb_properties_array_t *enb_properties;
1926

1927 1928 1929 1930 1931 1932 1933
  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,
1934
    LONG_OPTION_NO_L2_CONNECT,
1935 1936
    LONG_OPTION_RXGAIN,
    LONG_OPTION_TXGAIN,
1937
  };
1938

1939 1940 1941 1942 1943 1944 1945
  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},
1946
    {"ue_rxgain",   required_argument,  NULL, LONG_OPTION_RXGAIN},
1947
    {"ue_txgain",   required_argument,  NULL, LONG_OPTION_TXGAIN},
1948 1949 1950
    {NULL, 0, NULL, 0}
  };

1951
  while ((c = getopt_long (argc, argv, "C:dK:g:F:G:hqO:m:SUVRM:r:P:Ws:t:x:",long_options,NULL)) != -1) {
1952 1953 1954 1955 1956
    switch (c) {
    case LONG_OPTION_ULSCH_MAX_CONSECUTIVE_ERRORS:
      ULSCH_max_consecutive_errors = atoi(optarg);
      printf("Set ULSCH_max_consecutive_errors = %d\n",ULSCH_max_consecutive_errors);
      break;
1957

1958 1959 1960 1961 1962
    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;
1963

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

1970 1971 1972 1973 1974
    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;
1975

1976 1977 1978
    case LONG_OPTION_DEBUG_UE_PRACH:
      mode = debug_prach;
      break;
1979

1980 1981 1982
    case LONG_OPTION_NO_L2_CONNECT:
      mode = no_L2_connect;
      break;
1983

1984
    case LONG_OPTION_RXGAIN:
1985 1986
      for (i=0; i<4; i++)
        rx_gain[0][i] = atof(optarg);
1987

1988
      break;
1989

1990 1991 1992
    case LONG_OPTION_TXGAIN:
      for (i=0; i<4; i++)
        tx_gain[0][i] = atof(optarg);
1993

1994
      break;
1995

1996 1997 1998
    case 'M':
#ifdef ETHERNET
      strcpy(rrh_eNB_ip,optarg);
1999
#endif
2000
      break;
2001

2002
    case 'C':
2003 2004 2005 2006 2007 2008
      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]);
2009
      }
2010

2011 2012
      UE_scan=0;
      break;
2013

2014 2015 2016 2017
    case 'd':
#ifdef XFORMS
      do_forms=1;
      printf("Running with XFORMS!\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2018
#endif
2019
      break;
2020

2021 2022 2023
    case 'K':
#if defined(ENABLE_ITTI)
      itti_dump_file = strdup(optarg);
2024
#else
2025
      printf("-K option is disabled when ENABLE_ITTI is not defined\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2026
#endif
2027
      break;
2028

2029 2030 2031
    case 'O':
      conf_config_file_name = optarg;
      break;
2032

2033 2034 2035
    case 'U':
      UE_flag = 1;
      break;
2036

2037 2038 2039
    case 'm':
      target_dl_mcs = atoi (optarg);
      break;
2040

2041 2042 2043
    case 't':
      target_ul_mcs = atoi (optarg);
      break;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2044
#ifdef OPENAIR2
2045

2046 2047 2048 2049 2050 2051 2052
    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");
      /*
2053 2054 2055
      if (optarg == NULL){
      in_ip[0] =NULL;
      printf("Enabling OPT for wireshark for local interface");
2056
      } else {
2057 2058 2059
      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);
2060 2061 2062
      }
      */
      break;
2063

2064
    case 'P':
2065 2066
      opt_type = OPT_PCAP;
      opt_enabled=1;
2067 2068 2069 2070 2071

      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");
2072
      } else {
2073 2074 2075
        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);
2076
      }
2077 2078

      break;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2079
#endif
2080

Raymond Knopp's avatar
 
Raymond Knopp committed
2081 2082 2083
    case 'V':
      ouput_vcd = 1;
      break;
2084

Raymond Knopp's avatar
 
Raymond Knopp committed
2085
    case  'q':
Raymond Knopp's avatar
 
Raymond Knopp committed
2086 2087
      opp_enabled = 1;
      break;
2088

Raymond Knopp's avatar
 
Raymond Knopp committed
2089 2090 2091
    case  'R' :
      online_log_messages =1;
      break;
2092

Raymond Knopp's avatar
 
Raymond Knopp committed
2093
    case 'r':
2094
      UE_scan = 0;
2095

2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121
      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
2122
      }
2123

2124
      break;
2125

Raymond Knopp's avatar
 
Raymond Knopp committed
2126
    case 's':
2127
#if defined(OAI_USRP) || defined(CPRIGW)
Raymond Knopp's avatar
 
Raymond Knopp committed
2128 2129

      clock_src = atoi(optarg);
2130

Raymond Knopp's avatar
 
Raymond Knopp committed
2131
      if (clock_src == 0) {
2132 2133 2134 2135 2136
        //  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
2137
      }
2138

Raymond Knopp's avatar
 
Raymond Knopp committed
2139 2140 2141 2142
#else
      printf("Note: -s not defined for ExpressMIMO2\n");
#endif
      break;
2143

2144 2145 2146 2147
    case 'S':
      exit_missed_slots=0;
      printf("Skip exit for missed slots\n");
      break;
2148

2149
    case 'g':
Raymond Knopp's avatar
 
Raymond Knopp committed
2150
      glog_level=atoi(optarg); // value between 1 - 9
2151
      break;
2152 2153

    case 'F':
2154
#ifdef EXMIMO
2155 2156
      sprintf(rxg_fname,"%srxg.lime",optarg);
      rxg_fd = fopen(rxg_fname,"r");
2157

2158
      if (rxg_fd) {
2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176
        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);

2177
#endif
2178
      break;
2179

2180 2181 2182
    case 'G':
      glog_verbosity=atoi(optarg);// value from 0, 0x5, 0x15, 0x35, 0x75
      break;
2183

2184 2185
    case 'x':
      transmission_mode = atoi(optarg);
2186

2187
      if (transmission_mode > 2) {
2188 2189
        printf("Transmission mode > 2 (%d) not supported for the moment\n",transmission_mode);
        exit(-1);
2190
      }
2191

2192
      break;
2193 2194 2195 2196
    case 'h':
      help ();
      exit (-1);
       
Raymond Knopp's avatar
 
Raymond Knopp committed
2197
    default:
2198 2199
      help ();
      exit (-1);
Raymond Knopp's avatar
 
Raymond Knopp committed
2200
      break;
2201 2202
    }
  }
2203

Raymond Knopp's avatar
 
Raymond Knopp committed
2204 2205
  if (UE_flag == 0)
    AssertFatal(conf_config_file_name != NULL,"Please provide a configuration file\n");
2206 2207


Raymond Knopp's avatar
 
Raymond Knopp committed
2208
  if ((UE_flag == 0) && (conf_config_file_name != NULL)) {
2209
    int i,j;
2210

Raymond Knopp's avatar
 
Raymond Knopp committed
2211
    NB_eNB_INST = 1;
2212

Raymond Knopp's avatar
 
Raymond Knopp committed
2213 2214
    /* Read eNB configuration file */
    enb_properties = enb_config_init(conf_config_file_name);
2215

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

Raymond Knopp's avatar
 
Raymond Knopp committed
2220
    /* Update some simulation parameters */
2221
    for (i=0; i < enb_properties->number; i++) {
2222
      AssertFatal (MAX_NUM_CCs == enb_properties->properties[i]->nb_cc,
2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239
                   "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
2240 2241
      }

2242

2243
#ifdef OPENAIR2
2244

2245 2246 2247
      init_all_otg(0);
      g_otg->seed = 0;
      init_seeds(g_otg->seed);
2248 2249 2250 2251 2252 2253 2254 2255 2256 2257

      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");
2258
      }
2259

2260
      init_predef_traffic(enb_properties->properties[i]->num_otg_elements, 1);
2261

2262
#endif
2263

2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277
      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
2278 2279 2280 2281 2282 2283
# 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
2284 2285 2286
#if defined (ENABLE_SECURITY)
      osa_log_level                  = enb_properties->properties[i]->osa_log_level;
      osa_log_verbosity              = enb_properties->properties[i]->osa_log_verbosity;
2287
#endif
Florian Kaltenberger's avatar
Florian Kaltenberger committed
2288

Raymond Knopp's avatar
 
Raymond Knopp committed
2289
      // adjust the log
2290
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
2291 2292 2293 2294 2295 2296 2297 2298 2299 2300
        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
2301
      } // CC_id
2302
    }// i
2303
  } else if ((UE_flag == 1) && (conf_config_file_name != NULL)) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2304 2305 2306 2307 2308 2309

    // 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
2310
}
2311

2312 2313
int main( int argc, char **argv )
{
Raymond Knopp's avatar
 
Raymond Knopp committed
2314
  int i,aa,card;
Lionel Gauthier's avatar
Lionel Gauthier committed
2315
#if defined (XFORMS) || defined (EMOS) || defined (EXMIMO)
Raymond Knopp's avatar
 
Raymond Knopp committed
2316
  void *status;
2317
#endif
2318

Raymond Knopp's avatar
 
Raymond Knopp committed
2319
  int CC_id;
Raymond Knopp's avatar
 
Raymond Knopp committed
2320
  uint16_t Nid_cell = 0;
2321
  uint8_t  cooperation_flag=0,  abstraction_flag=0;
2322
#ifndef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
2323
  uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2;
2324 2325 2326
#endif

#ifdef ENABLE_TCXO
Raymond Knopp's avatar
 
Raymond Knopp committed
2327
  unsigned int tcxo = 114;
2328 2329
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
2330
#if defined (XFORMS)
2331 2332
  int ret;
#endif
2333
#if defined (EMOS) || (! defined (RTAI))
Raymond Knopp's avatar
 
Raymond Knopp committed
2334
  int error_code;
2335
#endif
2336

2337 2338 2339 2340 2341
#ifdef DEBUG_CONSOLE
  setvbuf(stdout, NULL, _IONBF, 0);
  setvbuf(stderr, NULL, _IONBF, 0);
#endif

2342 2343 2344
  PHY_VARS_UE *UE[MAX_NUM_CCs];

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

2347
  memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
Raymond Knopp's avatar
 
Raymond Knopp committed
2348
  set_latency_target();
2349

2350

2351

2352
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2353 2354
    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 */
2355
    frame_parms[CC_id]->frame_type         = FDD; /* TDD */
Raymond Knopp's avatar
 
Raymond Knopp committed
2356 2357
    frame_parms[CC_id]->tdd_config          = 3;
    frame_parms[CC_id]->tdd_config_S        = 0;
2358 2359
    frame_parms[CC_id]->N_RB_DL             = 100;
    frame_parms[CC_id]->N_RB_UL             = 100;
Raymond Knopp's avatar
 
Raymond Knopp committed
2360
    frame_parms[CC_id]->Ncp                 = NORMAL;
Raymond Knopp's avatar
 
Raymond Knopp committed
2361 2362
    frame_parms[CC_id]->Ncp_UL              = NORMAL;
    frame_parms[CC_id]->Nid_cell            = Nid_cell;
Raymond Knopp's avatar
 
Raymond Knopp committed
2363
    frame_parms[CC_id]->num_MBSFN_config    = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2364 2365 2366
    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
2367
  }
2368

2369 2370 2371 2372 2373
  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];
2374
    //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
2375
  }
2376 2377
  logInit();
 
2378
  get_options (argc, argv); //Command-line options
2379 2380 2381 2382 2383
 
  // initialize mscgen log
  MSC_INIT(MSC_E_UTRAN);
  
  // initialize the log (see log.h for details)
Florian Kaltenberger's avatar
Florian Kaltenberger committed
2384 2385
  set_glog(glog_level, glog_verbosity);

2386 2387
  //randominit (0);
  set_taus_seed (0);
Raymond Knopp's avatar
 
Raymond Knopp committed
2388

2389 2390
  if (UE_flag==1) {
    printf("configuring for UE\n");
2391

2392
    set_comp_log(HW,      LOG_DEBUG,  LOG_HIGH, 1);
2393
#ifdef OPENAIR2
2394
    set_comp_log(PHY,     LOG_DEBUG,   LOG_HIGH, 1);
2395
#else
2396
    set_comp_log(PHY,     LOG_INFO,   LOG_HIGH, 1);
2397
#endif
2398 2399 2400 2401 2402
    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);
2403
#if defined(ENABLE_ITTI)
2404
    set_comp_log(EMU,     LOG_INFO,   LOG_MED, 1);
2405
# if defined(ENABLE_USE_MME)
2406
    set_comp_log(NAS,     LOG_INFO,   LOG_HIGH, 1);
2407 2408
# endif
#endif
2409 2410
  } else {
    printf("configuring for eNB\n");
2411

2412
    set_comp_log(HW,      hw_log_level, hw_log_verbosity, 1);
2413
#ifdef OPENAIR2
2414 2415 2416 2417 2418
    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);

2419
#else
2420
    set_comp_log(PHY,     LOG_INFO,   LOG_HIGH, 1);
2421
#endif
2422 2423 2424 2425
    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);
2426
#if defined(ENABLE_ITTI)
2427
    set_comp_log(EMU,     LOG_INFO,   LOG_MED, 1);
2428
# if defined(ENABLE_USE_MME)
2429 2430 2431 2432
    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);
2433
# endif
2434
#if defined(ENABLE_SECURITY)
2435
    set_comp_log(OSA,    osa_log_level,   osa_log_verbosity, 1);
2436
#endif
2437
#endif
2438
#ifdef LOCALIZATION
2439 2440 2441 2442 2443 2444 2445 2446 2447
    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
2448
    }
2449
  }
2450

Raymond Knopp's avatar
 
Raymond Knopp committed
2451 2452
  if (ouput_vcd) {
    if (UE_flag==1)
2453
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_UE.vcd");
Raymond Knopp's avatar
 
Raymond Knopp committed
2454
    else
2455
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_eNB.vcd");
Raymond Knopp's avatar
 
Raymond Knopp committed
2456
  }
2457

2458 2459
  if (opp_enabled ==1)
    reset_opp_meas();
2460

2461
#if defined(ENABLE_ITTI)
2462

Raymond Knopp's avatar
 
Raymond Knopp committed
2463 2464
  if (UE_flag == 1) {
    log_set_instance_type (LOG_INSTANCE_UE);
2465
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
2466 2467
    log_set_instance_type (LOG_INSTANCE_ENB);
  }
2468

Raymond Knopp's avatar
 
Raymond Knopp committed
2469
  itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, itti_dump_file);
2470
#endif
2471
#ifdef OPENAIR2
2472

2473 2474
  if (opt_type != OPT_NONE) {
    radio_type_t radio_type;
2475

2476 2477
    if (frame_parms[0]->frame_type == FDD)
      radio_type = RADIO_TYPE_FDD;
2478
    else
2479
      radio_type = RADIO_TYPE_TDD;
2480

2481 2482 2483
    if (init_opt(in_path, in_ip, NULL, radio_type) == -1)
      LOG_E(OPT,"failed to run OPT \n");
  }
2484

2485
#endif
2486
#ifdef NAS_NETLINK
Raymond Knopp's avatar
 
Raymond Knopp committed
2487
  netlink_init();
2488 2489
#endif

2490
#if !defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
2491 2492 2493
  // to make a graceful exit when ctrl-c is pressed
  signal(SIGSEGV, signal_handler);
  signal(SIGINT, signal_handler);
2494
#endif
2495 2496

#ifndef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
2497 2498 2499 2500
  check_clock();
#endif

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

2504 2505 2506 2507 2508 2509 2510 2511 2512
    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
2513 2514 2515 2516 2517 2518 2519 2520
    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;
2521 2522
    init_ul_hopping(frame_parms[CC_id]);
    init_frame_parms(frame_parms[CC_id],1);
2523 2524
    //   phy_init_top(frame_parms[CC_id]);
    phy_init_lte_top(frame_parms[CC_id]);
Raymond Knopp's avatar
 
Raymond Knopp committed
2525 2526 2527
  }


2528
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2529
    //init prach for openair1 test
2530
    frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22;
Raymond Knopp's avatar
 
Raymond Knopp committed
2531
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1;
2532
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2533 2534 2535
    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
2536
    // N_ZC = (prach_fmt <4)?839:139;
Raymond Knopp's avatar
 
Raymond Knopp committed
2537
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
2538 2539

  if (UE_flag==1) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2540 2541 2542
    NB_UE_INST=1;
    NB_INST=1;

Raymond Knopp's avatar
 
Raymond Knopp committed
2543 2544
    PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE**));
    PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_UE*)*MAX_NUM_CCs);
2545 2546

    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
2547 2548 2549 2550

      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
2551
#ifndef OPENAIR2
2552 2553 2554 2555 2556 2557 2558 2559 2560

      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
2561
      }
2562

2563
#endif
2564 2565 2566 2567 2568 2569


      UE[CC_id]->UE_scan = UE_scan;
      UE[CC_id]->mode    = mode;

      compute_prach_seq(&UE[CC_id]->lte_frame_parms.prach_config_common,
2570 2571 2572
                        UE[CC_id]->lte_frame_parms.frame_type,
                        UE[CC_id]->X_u);

2573
      UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1234;
2574
#ifndef OPENAIR2
2575
      UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1235;
2576
#endif
2577

2578
#ifdef EXMIMO
2579

2580 2581 2582 2583
      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
2584
      }
2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603

      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
2604
      }
2605

2606
#else
2607
      UE[CC_id]->rx_total_gain_dB =  (int)rx_gain[CC_id][0];
2608
#endif
2609

2610
      UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id];
2611

2612 2613


2614
#ifdef EXMIMO
2615

Raymond Knopp's avatar
 
Raymond Knopp committed
2616
      //N_TA_offset
2617
      if (UE[CC_id]->lte_frame_parms.frame_type == TDD) {
2618 2619 2620 2621 2622 2623 2624 2625
        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
2626
      }
2627

2628
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
2629
      //already taken care of in lte-softmodem
2630
      UE[CC_id]->N_TA_offset = 0;
2631
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2632
    }
2633

Raymond Knopp's avatar
 
Raymond Knopp committed
2634 2635 2636 2637
    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;
2638 2639 2640



Raymond Knopp's avatar
 
Raymond Knopp committed
2641
    //  printf("tx_max_power = %d -> amp %d\n",tx_max_power,get_tx_amp(tx_max_power,tx_max_power));
2642 2643 2644 2645 2646 2647 2648 2649 2650
  } 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;

2651
#ifndef OPENAIR2
2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667

      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
2668

2669
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
2670

2671
      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
2672

2673
#else
2674 2675 2676
      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
2677

2678 2679 2680
      // 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
2681

2682
#endif
2683

2684
#ifdef EXMIMO
2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695

      //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
2696
      }
2697

2698 2699 2700 2701
#else
      //already taken care of in lte-softmodem
      PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 0;
#endif
2702

2703
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
2704 2705


2706 2707 2708 2709 2710 2711 2712 2713 2714
    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;

  }
2715

2716

2717

Raymond Knopp's avatar
 
Raymond Knopp committed
2718
  dump_frame_parms(frame_parms[0]);
2719

Raymond Knopp's avatar
 
Raymond Knopp committed
2720
  if(frame_parms[0]->N_RB_DL == 100) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2721
    sample_rate = 30.72e6;
2722
#ifndef EXMIMO
2723
    openair0_cfg[0].samples_per_packet = 2048;
Raymond Knopp's avatar
 
Raymond Knopp committed
2724 2725 2726
    samples_per_frame = 307200;
    // from usrp_time_offset
    tx_forward_nsamps = 175;
2727
    tx_delay = 8;
Raymond Knopp's avatar
 
Raymond Knopp committed
2728
#endif
2729
  } else if(frame_parms[0]->N_RB_DL == 50) {
2730
    sample_rate = 15.36e6;
2731
#ifndef EXMIMO
2732
    openair0_cfg[0].samples_per_packet = 2048;
Raymond Knopp's avatar
 
Raymond Knopp committed
2733 2734
    samples_per_frame = 153600;
    tx_forward_nsamps = 95;
2735
    tx_delay = 5;
Raymond Knopp's avatar
 
Raymond Knopp committed
2736
#endif
2737
  } else if (frame_parms[0]->N_RB_DL == 25) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2738
    sample_rate = 7.68e6;
2739
#ifndef EXMIMO
2740
    openair0_cfg[0].samples_per_packet = 1024;
Raymond Knopp's avatar
 
Raymond Knopp committed
2741 2742
    samples_per_frame = 76800;
    tx_forward_nsamps = 70;
2743
    tx_delay = 6;
Raymond Knopp's avatar
 
Raymond Knopp committed
2744
#endif
2745
  } else if (frame_parms[0]->N_RB_DL == 6) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2746 2747
    sample_rate = 1.92e6;
#ifndef EXMIMO
2748
    openair0_cfg[0].samples_per_packet = 256;
Raymond Knopp's avatar
 
Raymond Knopp committed
2749 2750
    samples_per_frame = 19200;
    tx_forward_nsamps = 40;
2751
    tx_delay = 8;
Raymond Knopp's avatar
 
Raymond Knopp committed
2752 2753
#endif
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
2754 2755

#ifdef ETHERNET
2756

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

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

2763

2764
  for (card=0; card<MAX_CARDS; card++) {
2765
#ifndef EXMIMO
2766
    openair0_cfg[card].samples_per_packet = openair0_cfg[0].samples_per_packet;
2767 2768
#endif
    printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card,
2769 2770
           ((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
2771 2772
    openair0_cfg[card].Mod_id = 0;
#ifdef ETHERNET
2773 2774

    if (UE_flag) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2775 2776 2777
      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;
2778 2779 2780 2781
    } 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
2782
    }
2783

Raymond Knopp's avatar
 
Raymond Knopp committed
2784
#endif
2785 2786 2787
    openair0_cfg[card].sample_rate = sample_rate;
    openair0_cfg[card].tx_bw = bw;
    openair0_cfg[card].rx_bw = bw;
2788
    // in the case of the USRP, the following variables need to be initialized before the init
2789
    // since the USRP only supports one CC (for the moment), we initialize all the cards with first CC.
2790
    // in the case of EXMIMO2, these values are overwirtten in the function setup_eNB/UE_buffer
2791
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
2792 2793
    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));
2794 2795

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

2797
      openair0_cfg[card].tx_gain[i] = tx_gain[0][i];
2798
      openair0_cfg[card].rx_gain[i] = ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->rx_total_gain_eNB_dB :
2799
                                       PHY_vars_UE_g[0][0]->rx_total_gain_dB) - USRP_GAIN_OFFSET;  // calibrated for USRP B210 @ 2.6 GHz, 30.72 MS/s
2800

2801 2802
      switch(frame_parms[0]->N_RB_DL) {
      case 6:
2803 2804 2805
        openair0_cfg[card].rx_gain[i] -= 6;
        break;

2806
      case 25:
2807 2808 2809
        openair0_cfg[card].rx_gain[i] += 6;
        break;

2810
      case 50:
2811 2812 2813
        openair0_cfg[card].rx_gain[i] += 8;
        break;

2814
      default:
2815
        break;
2816
      }
2817

2818 2819
      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];
2820
      printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n",
2821 2822 2823 2824 2825
             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
2826
    }
2827

2828
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2829
  }
2830

2831
  printf("Initializing openair0 ...");
2832
  openair0_cfg[0].log_level = glog_level;
2833
  if (openair0_device_init(&openair0, &openair0_cfg[0]) <0) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2834 2835 2836
    printf("Exiting, cannot initialize device\n");
    exit(-1);
  }
2837

2838
  printf("Done\n");
2839 2840 2841

  mac_xface = malloc(sizeof(MAC_xface));

2842
#ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
2843
  int eMBMS_active=0;
2844

Raymond Knopp's avatar
 
Raymond Knopp committed
2845
  l2_init(frame_parms[0],eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL,
2846 2847 2848 2849
          0,// cba_group_active
          0); // HO flag


2850 2851
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
2852
  mac_xface->macphy_exit = &exit_fun;
2853

winckel's avatar
winckel committed
2854
#if defined(ENABLE_ITTI)
2855

Raymond Knopp's avatar
 
Raymond Knopp committed
2856
  if (create_tasks(UE_flag ? 0 : 1, UE_flag ? 1 : 0) < 0) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
2857
    printf("cannot create ITTI tasks\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2858 2859
    exit(-1); // need a softer mode
  }
2860

Raymond Knopp's avatar
 
Raymond Knopp committed
2861
  printf("ITTI tasks created\n");
winckel's avatar
winckel committed
2862
#endif
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2863 2864

#ifdef OPENAIR2
2865
  if (UE_flag==1) {
2866
    printf("Filling UE band info\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2867
    fill_ue_band_info();
2868
    mac_xface->dl_phy_sync_success (0, 0, 0, 1);
2869
  } else
2870
    mac_xface->mrbch_phy_sync_failure (0, 0, 0);
2871

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2872
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2873

2874
  /* #ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
2875 2876 2877 2878 2879 2880
  //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
2881 2882 2883 2884 2885 2886
  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
2887 2888 2889
  }
  init_predef_traffic(UE_flag ? 1 : 0, UE_flag ? 0 : 1);
  //  }
2890
  #endif */
Raymond Knopp's avatar
 
Raymond Knopp committed
2891

2892
#ifdef EXMIMO
2893
  number_of_cards = openair0_num_detected_cards;
2894 2895
#else
  number_of_cards = 1;
2896
#endif
2897

2898

2899

2900
  for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
2901
    rf_map[CC_id].card=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2902
    rf_map[CC_id].chain=CC_id;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
2903
  }
2904

Raymond Knopp's avatar
 
Raymond Knopp committed
2905 2906
  // connect the TX/RX buffers
  if (UE_flag==1) {
2907
    openair_daq_vars.timing_advance = 0;//170;
2908

2909
    if (setup_ue_buffers(UE,&openair0_cfg[0],rf_map)!=0) {
2910 2911 2912
      printf("Error setting up eNB buffer\n");
      exit(-1);
    }
2913

2914
    printf("Setting UE buffer to all-RX\n");
2915

2916
    // Set LSBs for antenna switch (ExpressMIMO)
2917
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2918
      for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++)
2919 2920
        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
2921
    }
2922

Raymond Knopp's avatar
 
Raymond Knopp committed
2923
    //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX;
2924
  } else {
2925
    openair_daq_vars.timing_advance = 0;
2926

2927 2928 2929 2930
    if (setup_eNB_buffers(PHY_vars_eNB_g[0],&openair0_cfg[0],rf_map)!=0) {
      printf("Error setting up eNB buffer\n");
      exit(-1);
    }
2931

2932
    printf("Setting eNB buffer to all-RX\n");
2933

2934
    // Set LSBs for antenna switch (ExpressMIMO)
2935
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2936
      for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++)
2937 2938
        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
2939
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
2940
  }
2941

2942
#ifdef EXMIMO
2943
  openair0_config(&openair0_cfg[0],UE_flag);
Raymond Knopp's avatar
 
Raymond Knopp committed
2944 2945
#endif

2946
  /*
Raymond Knopp's avatar
 
Raymond Knopp committed
2947 2948
      for (ant=0;ant<4;ant++)
      p_exmimo_config->rf.do_autocal[ant] = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2949
  */
2950 2951

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

Raymond Knopp's avatar
 
Raymond Knopp committed
2954 2955 2956 2957 2958 2959
  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);
2960
  else
Raymond Knopp's avatar
 
Raymond Knopp committed
2961
    printf("[OPENAIR][SCHED][INIT] Problem creating EMOS FIFO %d, error_code %d\n",CHANSOUNDER_FIFO_MINOR,error_code);
2962

2963 2964
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
2965
  mlockall(MCL_CURRENT | MCL_FUTURE);
2966 2967

#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
2968
  // make main thread LXRT soft realtime
2969
  /* task = */ rt_task_init_schmod(nam2num("MAIN"), 9, 0, 0, SCHED_FIFO, 0xF);
Raymond Knopp's avatar
 
Raymond Knopp committed
2970 2971 2972 2973 2974

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

Raymond Knopp's avatar
 
Raymond Knopp committed
2977 2978
  pthread_cond_init(&sync_cond,NULL);
  pthread_mutex_init(&sync_mutex, NULL);
2979

2980
#if defined(ENABLE_ITTI)
2981

Florian Kaltenberger's avatar
Florian Kaltenberger committed
2982 2983 2984 2985 2986
  // 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);
  }
2987

2988
#endif
2989

Raymond Knopp's avatar
 
Raymond Knopp committed
2990 2991

  // this starts the DMA transfers
2992
#ifdef EXMIMO
2993

Raymond Knopp's avatar
 
Raymond Knopp committed
2994
  if (UE_flag!=1)
2995
    for (card=0; card<openair0_num_detected_cards; card++)
2996
      openair0_start_rt_acquisition(card);
2997

Raymond Knopp's avatar
 
Raymond Knopp committed
2998
#endif
2999 3000

#ifdef XFORMS
3001 3002
  int UE_id;

Raymond Knopp's avatar
 
Raymond Knopp committed
3003 3004
  if (do_forms==1) {
    fl_initialize (&argc, argv, NULL, 0, 0);
3005 3006

    if (UE_flag==0) {
3007
      form_stats_l2 = create_form_stats_form();
3008 3009 3010
      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");
3011 3012

      for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025
	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");
	  }
	}
3026
      }
3027
    } else {
3028 3029 3030 3031 3032 3033 3034
      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
3035
      if (openair_daq_vars.use_ia_receiver) {
3036 3037 3038 3039 3040
        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
3041 3042 3043
      }
    }

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

3046 3047
    if (ret == 0)
      pthread_setname_np( forms_thread, "xforms" );
3048

Raymond Knopp's avatar
 
Raymond Knopp committed
3049 3050
    printf("Scope thread created, ret=%d\n",ret);
  }
3051

3052 3053 3054
#endif

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3055 3056
  ret = pthread_create(&thread3, NULL, emos_thread, NULL);
  printf("EMOS thread created, ret=%d\n",ret);
jiangx's avatar
jiangx committed
3057 3058
  ret = pthread_create(&thread4, NULL, gps_thread, NULL);
  printf("GPS thread created, ret=%d\n",ret);
3059 3060
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3061
  rt_sleep_ns(10*FRAME_PERIOD);
3062 3063

#ifndef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3064
  pthread_attr_init (&attr_dlsch_threads);
3065
  pthread_attr_setstacksize(&attr_dlsch_threads,4*PTHREAD_STACK_MIN);
3066

3067
  pthread_attr_init (&attr_UE_thread);
3068
  pthread_attr_setstacksize(&attr_UE_thread,8192);//5*PTHREAD_STACK_MIN);
3069

3070
#ifndef LOWLATENCY
3071 3072
  sched_param_UE_thread.sched_priority = sched_get_priority_max(SCHED_FIFO);
  pthread_attr_setschedparam(&attr_UE_thread,&sched_param_UE_thread);
3073
  sched_param_dlsch.sched_priority = sched_get_priority_max(SCHED_FIFO); //OPENAIR_THREAD_PRIORITY;
Raymond Knopp's avatar
 
Raymond Knopp committed
3074 3075
  pthread_attr_setschedparam  (&attr_dlsch_threads, &sched_param_dlsch);
  pthread_attr_setschedpolicy (&attr_dlsch_threads, SCHED_FIFO);
3076
  printf("Setting eNB_thread FIFO scheduling policy with priority %d \n", sched_param_dlsch.sched_priority);
3077
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3078

3079 3080
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3081 3082
  // start the main thread
  if (UE_flag == 1) {
3083
    printf("Intializing UE Threads ...\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3084
    init_UE_threads();
3085 3086 3087 3088 3089
#ifdef DLSCH_THREAD
    init_rx_pdsch_thread();
    rt_sleep_ns(FRAME_PERIOD/10);
    init_dlsch_threads();
#endif
3090

3091
    sleep(1);
3092
#ifdef RTAI
3093
    main_ue_thread = rt_thread_create(UE_thread, NULL, 100000000);
3094
#else
3095
    error_code = pthread_create(&main_ue_thread, &attr_UE_thread, UE_thread, NULL);
3096

Raymond Knopp's avatar
 
Raymond Knopp committed
3097 3098 3099
    if (error_code!= 0) {
      LOG_D(HW,"[lte-softmodem.c] Could not allocate UE_thread, error %d\n",error_code);
      return(error_code);
3100
    } else {
3101 3102
      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
3103
    }
3104

3105
#endif
3106
    printf("UE threads created\n");
3107
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
3108 3109
    if (multi_thread>0) {
      init_eNB_proc();
3110
      sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3111 3112
      LOG_D(HW,"[lte-softmodem.c] eNB threads created\n");
    }
3113

3114
    printf("Creating main eNB_thread \n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3115
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3116
    main_eNB_thread = rt_thread_create(eNB_thread, NULL, PTHREAD_STACK_MIN);
Raymond Knopp's avatar
 
Raymond Knopp committed
3117
#else
3118
    error_code = pthread_create( &main_eNB_thread, &attr_dlsch_threads, eNB_thread, NULL );
3119

Raymond Knopp's avatar
 
Raymond Knopp committed
3120 3121 3122
    if (error_code!= 0) {
      LOG_D(HW,"[lte-softmodem.c] Could not allocate eNB_thread, error %d\n",error_code);
      return(error_code);
3123
    } else {
3124 3125
      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
3126
    }
3127

Raymond Knopp's avatar
 
Raymond Knopp committed
3128 3129
#endif
  }
3130

Raymond Knopp's avatar
 
Raymond Knopp committed
3131
  // Sleep to allow all threads to setup
Raymond Knopp's avatar
 
Raymond Knopp committed
3132
  sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3133

3134
#ifdef USE_MME
3135

3136 3137 3138
  while (start_UE == 0) {
    sleep(1);
  }
3139

3140 3141
#endif

3142
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3143
#ifndef USRP_DEBUG
Raymond Knopp's avatar
 
Raymond Knopp committed
3144
  openair0.trx_start_func(&openair0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3145
  //  printf("returning from usrp start streaming: %llu\n",get_usrp_time(&openair0));
Raymond Knopp's avatar
 
Raymond Knopp committed
3146
#endif
3147 3148
#endif

3149

Raymond Knopp's avatar
 
Raymond Knopp committed
3150
  pthread_mutex_lock(&sync_mutex);
3151
  sync_var=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3152 3153
  pthread_cond_broadcast(&sync_cond);
  pthread_mutex_unlock(&sync_mutex);
3154

Raymond Knopp's avatar
 
Raymond Knopp committed
3155 3156 3157
  // wait for end of program
  printf("TYPE <CTRL-C> TO TERMINATE\n");
  //getchar();
3158 3159

#if defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
3160 3161
  printf("Entering ITTI signals handler\n");
  itti_wait_tasks_end();
3162
  oai_exit=1;
3163
#else
3164

Raymond Knopp's avatar
 
Raymond Knopp committed
3165 3166
  while (oai_exit==0)
    rt_sleep_ns(FRAME_PERIOD);
3167

3168
#endif
3169

Raymond Knopp's avatar
 
Raymond Knopp committed
3170
  // stop threads
3171
#ifdef XFORMS
Raymond Knopp's avatar
 
Raymond Knopp committed
3172
  printf("waiting for XFORMS thread\n");
3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186

  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++) {
3187 3188 3189 3190
	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
3191
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
3192
    }
3193 3194
  }

3195 3196
#endif

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3199 3200
  // cleanup
  if (UE_flag == 1) {
3201
#ifdef EXMIMO
3202
#ifdef RTAI
3203
    rt_thread_join(main_ue_thread);
3204
#else
3205
    pthread_join(main_ue_thread,&status);
3206 3207
#endif
#ifdef DLSCH_THREAD
Raymond Knopp's avatar
 
Raymond Knopp committed
3208 3209
    cleanup_dlsch_threads();
    cleanup_rx_pdsch_thread();
3210
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3211
#endif
3212
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
3213
#ifdef DEBUG_THREADS
Raymond Knopp's avatar
 
Raymond Knopp committed
3214
    printf("Joining eNB_thread ...");
Raymond Knopp's avatar
 
Raymond Knopp committed
3215
#endif
3216
#ifdef RTAI
3217
    rt_thread_join(main_eNB_thread);
3218
#else
3219 3220
    int *eNB_thread_status_p;
    int result = pthread_join( main_eNB_thread, (void**)&eNB_thread_status_p );
Raymond Knopp's avatar
 
Raymond Knopp committed
3221
#ifdef DEBUG_THREADS
3222

3223
    if (result != 0) {
3224
      printf( "\nError joining main_eNB_thread.\n" );
3225
    } else {
3226 3227 3228 3229 3230
      if (eNB_thread_status_p) {
        printf( "status %d\n", *eNB_thread_status_p );
      } else {
        printf( "The thread was killed. No status available.\n");
      }
3231
    }
3232

3233 3234
#else
    UNUSED(result);
3235 3236
#endif // DEBUG_THREADS
#endif // RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3237

Raymond Knopp's avatar
 
Raymond Knopp committed
3238 3239 3240
    if (multi_thread>0) {
      printf("Killing eNB processing threads\n");
      kill_eNB_proc();
Raymond Knopp's avatar
 
Raymond Knopp committed
3241

Raymond Knopp's avatar
 
Raymond Knopp committed
3242
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3243
  }
3244

3245
#ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
3246
  //cleanup_pdcp_thread();
3247 3248
#endif

3249
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3250
  stop_rt_timer();
3251
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3252 3253
  pthread_cond_destroy(&sync_cond);
  pthread_mutex_destroy(&sync_mutex);
3254

3255

3256
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3257
  printf("stopping card\n");
3258
  openair0_stop(0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3259 3260
  printf("closing openair0_lib\n");
  openair0_close();
Raymond Knopp's avatar
 
Raymond Knopp committed
3261
#endif
3262 3263

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3264 3265 3266
  printf("waiting for EMOS thread\n");
  pthread_cancel(thread3);
  pthread_join(thread3,&status);
jiangx's avatar
jiangx committed
3267 3268 3269
  printf("waiting for GPS thread\n");
  pthread_cancel(thread4);
  pthread_join(thread4,&status);
3270 3271 3272
#endif

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3273 3274
  error_code = rtf_destroy(CHANSOUNDER_FIFO_MINOR);
  printf("[OPENAIR][SCHED][CLEANUP] EMOS FIFO closed, error_code %d\n", error_code);
3275 3276
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3277
  if (ouput_vcd)
3278
    VCD_SIGNAL_DUMPER_CLOSE();
3279

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3280
#ifdef OPENAIR2
3281

3282
  if (opt_enabled == 1)
3283
    terminate_opt();
3284

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3285
#endif
3286

Raymond Knopp's avatar
 
Raymond Knopp committed
3287
  logClean();
3288

Raymond Knopp's avatar
 
Raymond Knopp committed
3289 3290
  return 0;
}
3291 3292


3293 3294 3295
/* 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
3296
   antennas are mapped to successive RF chains on the same card. */
3297 3298
int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs])
{
3299

3300
  int i, CC_id;
3301
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3302
  uint16_t N_TA_offset = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3303 3304
#else
  int j;
Raymond Knopp's avatar
 
Raymond Knopp committed
3305
#endif
3306
  LTE_DL_FRAME_PARMS *frame_parms;
3307

Raymond Knopp's avatar
 
Raymond Knopp committed
3308

3309 3310
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    if (phy_vars_eNB[CC_id]) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3311 3312
      frame_parms = &(phy_vars_eNB[CC_id]->lte_frame_parms);
      printf("setup_eNB_buffers: frame_parms = %p\n",frame_parms);
3313
    } else {
3314 3315
      printf("phy_vars_eNB[%d] not initialized\n", CC_id);
      return(-1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3316
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3317

3318
#ifndef EXMIMO
3319

3320 3321
    if (frame_parms->frame_type == TDD) {
      if (frame_parms->N_RB_DL == 100)
3322
        N_TA_offset = 624;
3323
      else if (frame_parms->N_RB_DL == 50)
3324
        N_TA_offset = 624/2;
3325
      else if (frame_parms->N_RB_DL == 25)
3326
        N_TA_offset = 624/4;
Raymond Knopp's avatar
 
Raymond Knopp committed
3327
    }
3328

Raymond Knopp's avatar
 
Raymond Knopp committed
3329
#endif
3330 3331


3332 3333 3334



Raymond Knopp's avatar
 
Raymond Knopp committed
3335
    // replace RX signal buffers with mmaped HW versions
3336
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3337 3338 3339
    openair0_cfg[CC_id].tx_num_channels = 0;
    openair0_cfg[CC_id].rx_num_channels = 0;

3340
    for (i=0; i<frame_parms->nb_antennas_rx; i++) {
3341 3342 3343
      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];
3344

3345
      if (openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i]) {
3346 3347 3348 3349 3350 3351
        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++;
3352
      }
3353

3354
      printf("rxdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]);
3355 3356 3357 3358

      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;
3359
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
3360
    }
3361 3362

    for (i=0; i<frame_parms->nb_antennas_tx; i++) {
3363 3364 3365
      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];
3366

3367
      if (openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i]) {
3368 3369 3370 3371 3372 3373
        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++;
3374
      }
3375

3376
      printf("txdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3377 3378 3379 3380

      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;
3381
      }
3382
    }
3383

3384
#else // not EXMIMO
3385 3386 3387
    rxdata = (int32_t**)malloc16(frame_parms->nb_antennas_rx*sizeof(int32_t*));
    txdata = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*));

3388
    for (i=0; i<frame_parms->nb_antennas_rx; i++) {
3389
      free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]);
Raymond Knopp's avatar
 
Raymond Knopp committed
3390
      rxdata[i] = (int32_t*)(16 + malloc16(16+samples_per_frame*sizeof(int32_t)));
3391 3392 3393
      phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i] = rxdata[i]-N_TA_offset; // N_TA offset for TDD
      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
3394
    }
3395 3396

    for (i=0; i<frame_parms->nb_antennas_tx; i++) {
3397
      free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
ghaddab's avatar
ghaddab committed
3398
      txdata[i] = (int32_t*)(16 + malloc16(16 + samples_per_frame*sizeof(int32_t)));
3399 3400
      phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i] = txdata[i];
      memset(txdata[i], 0, samples_per_frame*sizeof(int32_t));
3401
      printf("txdata[%d] @ %p\n", i, phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3402

Raymond Knopp's avatar
 
Raymond Knopp committed
3403
    }
3404

Raymond Knopp's avatar
 
Raymond Knopp committed
3405
#endif
3406
  }
3407

3408
  return(0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3409
}
3410

3411 3412
void reset_opp_meas(void)
{
3413 3414 3415
  int sfn;
  reset_meas(&softmodem_stats_mt);
  reset_meas(&softmodem_stats_hw);
3416

3417 3418 3419 3420 3421 3422
  for (sfn=0; sfn < 10; sfn++) {
    reset_meas(&softmodem_stats_tx_sf[sfn]);
    reset_meas(&softmodem_stats_rx_sf[sfn]);
  }
}

3423 3424
void print_opp_meas(void)
{
3425 3426 3427
  int sfn=0;
  print_meas(&softmodem_stats_mt, "Main ENB Thread", NULL, NULL);
  print_meas(&softmodem_stats_hw, "HW Acquisation", NULL, NULL);
3428

3429 3430 3431 3432 3433
  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);
  }
}