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

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


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

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

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

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

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

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

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

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

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

#include "PHY/types.h"
70

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

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

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

#include "PHY/vars.h"
#include "MAC_INTERFACE/vars.h"
85
//#include "SCHED/defs.h"
86 87 88 89 90 91 92 93 94 95 96 97
#include "SCHED/vars.h"
#include "LAYER2/MAC/vars.h"

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

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

#ifdef OPENAIR2
#include "LAYER2/MAC/defs.h"
#include "LAYER2/MAC/vars.h"
98
#include "LAYER2/MAC/proto.h"
99 100 101 102 103 104 105 106 107
#include "RRC/LITE/vars.h"
#include "PHY_INTERFACE/vars.h"
#endif

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

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

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

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

#define FRAME_PERIOD    100000000ULL
#define DAQ_PERIOD      66667ULL

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

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

143
struct timing_info_t {
144 145 146 147
  //unsigned int frame, hw_slot, last_slot, next_slot;
  RTIME time_min, time_max, time_avg, time_last, time_now;
  //unsigned int mbox0, mbox1, mbox2, mbox_target;
  unsigned int n_samples;
148 149 150
} timing_info;


Raymond Knopp's avatar
 
Raymond Knopp committed
151

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

Raymond Knopp's avatar
 
Raymond Knopp committed
154 155
int32_t **rxdata;
int32_t **txdata;
156 157
int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]);
int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]);
158

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

#ifdef RTAI
171

172 173
static long                      main_eNB_thread;
static long                      main_ue_thread;
174

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

179
pthread_attr_t                  attr_dlsch_threads;
180 181
pthread_attr_t                  attr_UE_thread;

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

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

191

192 193


194
struct sched_param              sched_param_UE_thread;
195

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
212

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

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

223

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
234

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

238

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

242
openair0_rf_map rf_map[MAX_NUM_CCs];
243

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

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

253 254
FILE *input_fd=NULL;

255

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

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
296
unsigned int samples_per_frame = 307200;
297
unsigned int tx_forward_nsamps=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
298 299 300
int tx_delay;

#endif
301 302

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
324

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

Raymond Knopp's avatar
 
Raymond Knopp committed
333

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
362 363 364

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

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

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

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

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


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

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

407 408 409 410
    // print out all the frames to stderr
    fprintf(stderr, "Error: signal %d:\n", sig);
    backtrace_symbols_fd(array, size, 2);
    exit(-1);
411 412
  } else {
    printf("trying to exit gracefully...\n");
413
    oai_exit = 1;
414 415
  }
}
416
#endif
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431
#define KNRM  "\x1B[0m"
#define KRED  "\x1B[31m"
#define KGRN  "\x1B[32m"
#define KBLU  "\x1B[34m"
#define RESET "\033[0m"

void help (void) {
  printf (KGRN "Usage:\n");
  printf("  sudo -E lte-softmodem [options]\n");
  printf("  sudo -E ./lte-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.openEPC.conf -S -V -m 26 -t 16 -x 1 --ulsch-max-errors 100 -W\n\n");
  printf("Options:\n");
  printf("  --ulsch-max-errors set the max ULSCH erros\n");
  printf("  --calib-ue-rx set UE RX calibration\n");
  printf("  --calib-ue-rx-med \n");
  printf("  --calib-ue-rxbyp\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
432 433
  printf("  --debug-ue-prach run normal prach power ramping, but don't continue random-access\n");
  printf("  --calib-prach-tx run normal prach with maximum power, but don't continue random-access\n");
434
  printf("  --no-L2-connect bypass L2 and upper layers\n");
435 436 437 438
  printf("  --ue-rxgain set UE RX gain\n");
  printf("  --ue-txgain set UE TX gain\n");
  printf("  --ue-scan_carrier set UE to scan around carrier\n");
  printf("  --loop-memory get softmodem (UE) to loop through memory instead of acquiring from HW\n");
439 440 441 442 443 444 445 446 447 448 449
  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");
kaltenbe's avatar
kaltenbe committed
450
  printf("  -r Set the PRB, valid values: 6, 25, 50, 100  \n");    
451 452 453 454 455 456
  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);    
457

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

  oai_exit = 1;

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

  //rt_sleep_ns(FRAME_PERIOD);

  //exit (-1);
}

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

Raymond Knopp's avatar
 
Raymond Knopp committed
494 495
  if (stat("/dev/cpu_dma_latency", &s) == 0) {
    latency_target_fd = open("/dev/cpu_dma_latency", O_RDWR);
496

Raymond Knopp's avatar
 
Raymond Knopp committed
497 498
    if (latency_target_fd == -1)
      return;
499

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

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

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

512
#ifdef XFORMS
513

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

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

527 528 529
      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;
530 531 532 533 534 535

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

539 540 541
    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;
542 543 544
  }
}

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

555
  sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
Raymond Knopp's avatar
 
Raymond Knopp committed
556
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
557

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

560
# ifdef ENABLE_XFORMS_WRITE_STATS
561 562

  if (UE_flag==1)
Raymond Knopp's avatar
 
Raymond Knopp committed
563
    UE_stats  = fopen("UE_stats.txt", "w");
564
  else
Raymond Knopp's avatar
 
Raymond Knopp committed
565
    eNB_stats = fopen("eNB_stats.txt", "w");
566

567
#endif
568

Raymond Knopp's avatar
 
Raymond Knopp committed
569 570
  while (!oai_exit) {
    if (UE_flag==1) {
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
571
      len = dump_ue_stats (PHY_vars_UE_g[0][0], stats_buffer, 0, mode,rx_input_level_dBm);
knopp's avatar
knopp committed
572 573 574
      //fl_set_object_label(form_stats->stats_text, stats_buffer);
      fl_clear_browser(form_stats->stats_text);
      fl_add_browser_line(form_stats->stats_text, stats_buffer);
575

576 577 578 579 580
      phy_scope_UE(form_ue[0],
                   PHY_vars_UE_g[0][0],
                   0,
                   0,7);

Raymond Knopp's avatar
 
Raymond Knopp committed
581
    } else {
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
582 583
#ifdef OPENAIR2
      len = dump_eNB_l2_stats (stats_buffer, 0);
knopp's avatar
knopp committed
584 585 586
      //fl_set_object_label(form_stats_l2->stats_text, stats_buffer);
      fl_clear_browser(form_stats_l2->stats_text);
      fl_add_browser_line(form_stats_l2->stats_text, stats_buffer);
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
587 588
#endif
      len = dump_eNB_stats (PHY_vars_eNB_g[0][0], stats_buffer, 0);
589

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

593 594 595
      //fl_set_object_label(form_stats->stats_text, stats_buffer);
      fl_clear_browser(form_stats->stats_text);
      fl_add_browser_line(form_stats->stats_text, stats_buffer);
596

597
      for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
598 599 600 601 602
	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
603
      }
604

605
    }
606

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

612
  //  printf("%s",stats_buffer);
613

614
# ifdef ENABLE_XFORMS_WRITE_STATS
615

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

630
# endif
631

Raymond Knopp's avatar
 
Raymond Knopp committed
632
  pthread_exit((void*)arg);
633 634 635 636 637 638
}
#endif

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

jiangx's avatar
jiangx committed
639 640 641 642 643 644 645 646
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;

647
  sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
jiangx's avatar
jiangx committed
648
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
649

jiangx's avatar
jiangx committed
650 651 652
  printf("GPS thread has priority %d\n",sched_param.sched_priority);

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

jiangx's avatar
jiangx committed
654 655
#if GPSD_API_MAJOR_VERSION>=5
  ret = gps_open("127.0.0.1","2947",gps_data_ptr);
656

jiangx's avatar
jiangx committed
657 658 659
  if (ret!=0)
#else
  gps_data_ptr = gps_open("127.0.0.1","2947");
660 661

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

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

679 680 681

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

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

    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
695
      }
696 697 698 699 700 701 702 703
    } //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
704 705 706 707 708

  pthread_exit((void*) arg);

}

709 710 711 712 713 714 715 716 717 718 719
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;
720

jiangx's avatar
jiangx committed
721
  int channel_buffer_size,ret;
722

723 724 725
  time_t timer;
  struct tm *now;

726
  struct sched_param sched_param;
727 728

  sched_param.sched_priority = sched_get_priority_max(SCHED_FIFO)-1;
729
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
730

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

733 734 735 736 737 738 739 740 741 742 743 744
  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;

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

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


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

  dumpfile_id = fopen(dumpfile_name,"w");
763 764 765 766 767

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


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

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

780 781 782 783
    if (bytes<=0) {
      usleep(100);
      continue;
    }
784

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

789 790 791 792 793 794
    /*
    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);
    */
795

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

818 819 820 821
      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);
      }
822
    }
823 824
  }

825 826 827
  free(fifo2file_buffer);
  fclose(dumpfile_id);
  close(fifo);
828

829 830 831 832 833
  pthread_exit((void*) arg);

}
#endif

834 835


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

852 853 854 855 856
    LOG_D(EMU,"\n");
  }
}
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
857
#if defined(ENABLE_ITTI)
858
void *l2l1_task(void *arg)
859
{
Raymond Knopp's avatar
 
Raymond Knopp committed
860 861 862 863 864
  MessageDef *message_p = NULL;
  int         result;

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
865

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

875 876 877
      itti_receive_msg (TASK_L2L1, &message_p);

      switch (ITTI_MSG_ID(message_p)) {
Raymond Knopp's avatar
 
Raymond Knopp committed
878
      case INITIALIZE_MESSAGE:
879 880 881 882
        /* 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
883 884

      case TERMINATE_MESSAGE:
885 886 887 888
        printf("received terminate message\n");
        oai_exit=1;
        itti_exit_task ();
        break;
Raymond Knopp's avatar
 
Raymond Knopp committed
889 890

      default:
891 892
        LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
        break;
893
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
894
    } while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE);
895

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

Raymond Knopp's avatar
 
Raymond Knopp committed
918 919 920 921 922 923 924 925 926 927 928
    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);
929
  } while(!oai_exit);
930

Raymond Knopp's avatar
 
Raymond Knopp committed
931
  return NULL;
932 933 934
}
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
935

936 937
void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
938 939 940 941

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

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
954

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

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

1024 1025 1026 1027 1028 1029 1030 1031 1032
/* mutex, cond and variable to serialize phy proc TX calls
 * (this mechanism may be relaxed in the future for better
 * performances)
 */
static struct {
  pthread_mutex_t  mutex_phy_proc_tx;
  pthread_cond_t   cond_phy_proc_tx;
  volatile uint8_t phy_proc_CC_id;
} sync_phy_proc[NUM_ENB_THREADS];
Raymond Knopp's avatar
 
Raymond Knopp committed
1033

1034 1035 1036 1037 1038 1039 1040 1041 1042
/*!
 * \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
1043 1044

  eNB_proc_t *proc = (eNB_proc_t*)param;
1045 1046 1047 1048 1049 1050
  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");
  }
1051 1052 1053
  // set default return value
  eNB_thread_tx_status[proc->subframe] = 0;

1054 1055
  MSC_START_USE();

Raymond Knopp's avatar
 
Raymond Knopp committed
1056 1057
#ifdef RTAI
  RT_TASK *task;
1058
  char task_name[8];
Raymond Knopp's avatar
 
Raymond Knopp committed
1059

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

1063 1064 1065
  if (task == NULL) {
    LOG_E(PHY,"[SCHED][eNB] Problem starting eNB_proc_TX thread_index %d (%s)!!!!\n",proc->subframe,task_name);
    return 0;
1066 1067 1068 1069 1070
  } else {
    LOG_I(PHY,"[SCHED][eNB] eNB TX thread CC %d SF %d started with id %p\n",
          proc->CC_id,
          proc->subframe,
          task);
1071
  }
1072

Raymond Knopp's avatar
 
Raymond Knopp committed
1073
#else
1074
#ifdef LOWLATENCY
1075 1076 1077
  struct sched_attr attr;
  unsigned int flags = 0;

1078 1079 1080 1081
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1082

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

1089 1090 1091 1092
  if (sched_setattr(0, &attr, flags) < 0 ) {
    perror("[SCHED] eNB tx thread: sched_setattr failed\n");
    return &eNB_thread_tx_status[proc->subframe];
  }
1093

1094
  LOG_I( HW, "[SCHED] eNB TX deadline thread %d(Tid %ld) started on CPU %d\n", proc->subframe, gettid(), sched_getcpu() );
1095
#else
1096
  LOG_I( HW, "[SCHED][eNB] TX thread %d started on CPU %d TID %d\n", proc->subframe, sched_getcpu(),gettid() );
1097 1098
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
1099 1100 1101 1102 1103 1104 1105 1106
#endif

  mlockall(MCL_CURRENT | MCL_FUTURE);

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

1107
  while (!oai_exit) {
1108

1109
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe), 0 );
1110

1111
    if (pthread_mutex_lock(&proc->mutex_tx) != 0) {
1112
      LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc %d\n", proc->subframe );
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1113
      exit_fun("nothing to add");
1114
      break;
1115
    }
1116

1117
    while (proc->instance_cnt_tx < 0) {
1118 1119 1120
      // 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
1121
    }
1122

1123 1124 1125 1126 1127
    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
1128

1129 1130
    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 );
1131 1132 1133
    start_meas( &softmodem_stats_tx_sf[proc->subframe] );

    if (oai_exit) break;
1134

1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146
    if (((PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == TDD) &&
         ((subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_tx) == SF_DL) ||
          (subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_tx) == SF_S))) ||
        (PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == FDD)) {
      /* run PHY TX procedures the one after the other for all CCs to avoid race conditions
       * (may be relaxed in the future for performance reasons)
       */
      if (pthread_mutex_lock(&sync_phy_proc[proc->subframe].mutex_phy_proc_tx) != 0) {
        LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX proc %d\n", proc->subframe);
        exit_fun("nothing to add");
        break;
      }
1147 1148
      /* wait for our turn or oai_exit */
      while (sync_phy_proc[proc->subframe].phy_proc_CC_id != proc->CC_id && !oai_exit) {
1149 1150 1151
        pthread_cond_wait(&sync_phy_proc[proc->subframe].cond_phy_proc_tx,
                          &sync_phy_proc[proc->subframe].mutex_phy_proc_tx);
      }
ghaddab's avatar
ghaddab committed
1152

1153 1154 1155
      if (pthread_mutex_unlock(&sync_phy_proc[proc->subframe].mutex_phy_proc_tx) != 0) {
        LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc %d\n", proc->subframe);
        exit_fun("nothing to add");
1156 1157
      }

1158 1159 1160
      if (oai_exit)
        break;

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

1163
      /* we're done, let the next one proceed */
1164 1165 1166 1167 1168
      if (pthread_mutex_lock(&sync_phy_proc[proc->subframe].mutex_phy_proc_tx) != 0) {
        LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX proc %d\n", proc->subframe);
        exit_fun("nothing to add");
        break;
      }
1169 1170 1171 1172
      sync_phy_proc[proc->subframe].phy_proc_CC_id++;
      sync_phy_proc[proc->subframe].phy_proc_CC_id %= MAX_NUM_CCs;
      pthread_cond_broadcast(&sync_phy_proc[proc->subframe].cond_phy_proc_tx);
      if (pthread_mutex_unlock(&sync_phy_proc[proc->subframe].mutex_phy_proc_tx) != 0) {
1173
        LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc %d\n", proc->subframe);
1174 1175 1176
        exit_fun("nothing to add");
        break;
      }
1177
    }
1178

1179
    do_OFDM_mod_rt( proc->subframe_tx, PHY_vars_eNB_g[0][proc->CC_id] );
1180

1181 1182 1183 1184 1185
    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
1186

1187 1188 1189 1190 1191 1192 1193 1194 1195
    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++;
1196

1197 1198 1199
    if (proc->frame_tx==1024)
      proc->frame_tx=0;

1200 1201 1202
    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);

1203 1204 1205
  }

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

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

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

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


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

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

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

1248 1249
  MSC_START_USE();

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1267
#else
1268
#ifdef LOWLATENCY
1269 1270 1271
  struct sched_attr attr;
  unsigned int flags = 0;

1272 1273 1274 1275
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1276

Navid Nikaein's avatar
Navid Nikaein committed
1277
  /* This creates a 2ms reservation every 10ms period*/
1278
  attr.sched_policy = SCHED_DEADLINE;
1279 1280
  attr.sched_runtime  = 1   *  1000000; // each rx thread must finish its job in the worst case in 2ms
  attr.sched_deadline = 1   *  1000000; // each rx thread will finish within 2ms
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1281
  attr.sched_period   = 1   * 10000000; // each rx thread has a period of 10ms from the starting point
1282 1283

  if (sched_setattr(0, &attr, flags) < 0 ) {
1284
    perror("[SCHED] eNB RX sched_setattr failed\n");
1285
    return &eNB_thread_rx_status[proc->subframe];
1286
  }
1287

1288
  LOG_I( HW, "[SCHED] eNB RX deadline thread %d(TID %ld) started on CPU %d\n", proc->subframe, gettid(), sched_getcpu() );
1289
#else
1290
  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
1291
#endif
1292
#endif // RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
1293 1294 1295 1296 1297 1298 1299

  mlockall(MCL_CURRENT | MCL_FUTURE);

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

1300
  while (!oai_exit) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1301

1302
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 0 );
1303

Raymond Knopp's avatar
 
Raymond Knopp committed
1304
    if (pthread_mutex_lock(&proc->mutex_rx) != 0) {
1305 1306 1307
      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
1308 1309
    }

1310
    while (proc->instance_cnt_rx < 0) {
1311 1312 1313
      // 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
1314
    }
1315 1316 1317 1318 1319 1320 1321

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

1322 1323
    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 );
1324
    start_meas( &softmodem_stats_rx_sf[proc->subframe] );
1325

Raymond Knopp's avatar
 
Raymond Knopp committed
1326
    if (oai_exit) break;
1327

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

1331
      phy_procedures_eNB_RX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay );
Raymond Knopp's avatar
 
Raymond Knopp committed
1332
    }
1333 1334

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1338
    if (pthread_mutex_lock(&proc->mutex_rx) != 0) {
1339 1340 1341
      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
1342
    }
1343 1344 1345 1346 1347 1348 1349

    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
1350
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1351 1352

    proc->frame_rx++;
1353

Raymond Knopp's avatar
 
Raymond Knopp committed
1354 1355
    if (proc->frame_rx==1024)
      proc->frame_rx=0;
1356

1357 1358 1359
    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
1360
  }
1361 1362

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1365
#ifdef HARD_RT
Raymond Knopp's avatar
 
Raymond Knopp committed
1366 1367 1368 1369
  rt_make_soft_real_time();
#endif

#ifdef DEBUG_THREADS
1370
  printf( "Exiting eNB thread RX %d\n", proc->subframe );
Raymond Knopp's avatar
 
Raymond Knopp committed
1371 1372 1373 1374
#endif
  // clean task
#ifdef RTAI
  rt_task_delete(task);
Raymond Knopp's avatar
 
Raymond Knopp committed
1375 1376
#endif

1377 1378
  eNB_thread_rx_status[proc->subframe] = 0;
  return &eNB_thread_rx_status[proc->subframe];
Raymond Knopp's avatar
 
Raymond Knopp committed
1379 1380 1381 1382
}



Raymond Knopp's avatar
 
Raymond Knopp committed
1383

1384 1385
void init_eNB_proc(void)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1386
  int i;
Raymond Knopp's avatar
 
Raymond Knopp committed
1387 1388
  int CC_id;

1389 1390 1391 1392
  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] );
1393

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

1397
      pthread_attr_init( &attr_eNB_proc_rx[CC_id][i] );
1398

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

1402
#ifndef LOWLATENCY
1403
      // set the kernel scheduling policy and priority
Raymond Knopp's avatar
 
Raymond Knopp committed
1404 1405 1406 1407 1408 1409
      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);
1410
      printf("Setting OS scheduler to SCHED_FIFO for eNB [cc%d][thread%d] \n",CC_id, i);
1411 1412
#endif

1413 1414 1415
      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
1416
      PHY_vars_eNB_g[0][CC_id]->proc[i].CC_id = CC_id;
1417 1418 1419 1420 1421 1422
      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] );
1423 1424 1425 1426 1427
      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
1428 1429
      PHY_vars_eNB_g[0][CC_id]->proc[i].frame_tx = 0;
      PHY_vars_eNB_g[0][CC_id]->proc[i].frame_rx = 0;
1430
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
1431 1432
      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
1433
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
1434 1435
      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
1436
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1437
    }
1438 1439


1440
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
1441 1442
    // 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
1443

Raymond Knopp's avatar
 
Raymond Knopp committed
1444
    //PHY_vars_eNB_g[0][CC_id]->proc[0].frame_rx = 1023;
Raymond Knopp's avatar
 
Raymond Knopp committed
1445 1446
    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
1447
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
1448 1449
    // 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
1450
    //    PHY_vars_eNB_g[0][CC_id]->proc[7].frame_tx = 1;
Raymond Knopp's avatar
 
Raymond Knopp committed
1451 1452
    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
1453
    //    PHY_vars_eNB_g[0][CC_id]->proc[0].frame_tx = 1;
Raymond Knopp's avatar
 
Raymond Knopp committed
1454
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1455
  }
1456 1457 1458 1459 1460 1461 1462

  /* setup PHY proc TX sync mechanism */
  for (i=0; i<NUM_ENB_THREADS; i++) {
    pthread_mutex_init(&sync_phy_proc[i].mutex_phy_proc_tx, NULL);
    pthread_cond_init(&sync_phy_proc[i].cond_phy_proc_tx, NULL);
    sync_phy_proc[i].phy_proc_CC_id = 0;
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
1463
}
Raymond Knopp's avatar
 
Raymond Knopp committed
1464

1465 1466 1467 1468 1469 1470
/*!
 * \brief Terminate eNB TX and RX threads.
 */
void kill_eNB_proc(void)
{
  int *status;
Raymond Knopp's avatar
 
Raymond Knopp committed
1471

1472 1473
  for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++)
    for (int i=0; i<NUM_ENB_THREADS; i++) {
1474

Raymond Knopp's avatar
 
Raymond Knopp committed
1475
#ifdef DEBUG_THREADS
1476
      printf( "Killing TX CC_id %d thread %d\n", CC_id, i );
Raymond Knopp's avatar
 
Raymond Knopp committed
1477
#endif
1478 1479 1480

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1488
#ifdef DEBUG_THREADS
1489

1490 1491 1492 1493 1494 1495 1496 1497 1498
      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" );
        }
      }
1499

1500 1501
#else
      UNUSED(result)
Raymond Knopp's avatar
 
Raymond Knopp committed
1502
#endif
1503

Raymond Knopp's avatar
 
Raymond Knopp committed
1504
#ifdef DEBUG_THREADS
1505
      printf( "Killing RX CC_id %d thread %d\n", CC_id, i );
Raymond Knopp's avatar
 
Raymond Knopp committed
1506
#endif
1507 1508 1509 1510

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

1516 1517
#ifdef DEBUG_THREADS

1518 1519 1520 1521 1522 1523 1524 1525 1526
      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" );
        }
      }
1527

1528 1529
#else
      UNUSED(result)
Raymond Knopp's avatar
 
Raymond Knopp committed
1530
#endif
1531 1532 1533 1534 1535

      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
1536
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1537 1538 1539
}


Raymond Knopp's avatar
 
Raymond Knopp committed
1540 1541


1542

Raymond Knopp's avatar
 
Raymond Knopp committed
1543

1544 1545 1546 1547 1548 1549
/*!
 * \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 )
1550
{
1551 1552
  UNUSED(arg);
  static int eNB_thread_status;
1553

1554
  unsigned char slot;
1555
#ifdef EXMIMO
1556
  slot=0;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1557
  RTIME time_in;
Raymond Knopp's avatar
 
Raymond Knopp committed
1558
  volatile unsigned int *DAQ_MBOX = openair0_daq_cnt();
Raymond Knopp's avatar
 
Raymond Knopp committed
1559 1560
  int mbox_target=0,mbox_current=0;
  int hw_slot,delay_cnt;
Raymond Knopp's avatar
 
Raymond Knopp committed
1561 1562
  int diff;
  int ret;
1563
  int first_run=1;
Raymond Knopp's avatar
 
Raymond Knopp committed
1564
#else
1565 1566 1567
  // the USRP implementation operates on subframes, not slots
  // one subframe consists of one even and one odd slot
  slot = 1;
1568
  int spp;
1569
  int tx_launched = 0;
1570 1571 1572

  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
1573

1574
  int hw_subframe = 0; // 0..NUM_ENB_THREADS-1 => 0..9
1575
  spp = openair0_cfg[0].samples_per_packet;
1576 1577
  unsigned int rx_pos = 0;
  unsigned int tx_pos = spp*tx_delay;
Raymond Knopp's avatar
 
Raymond Knopp committed
1578
#endif
1579
  int CC_id=0;	
1580
  struct timespec trx_time0, trx_time1, trx_time2;
1581

1582
#ifdef RTAI
1583
  RT_TASK* task = rt_task_init_schmod(nam2num("eNBmain"), 0, 0, 0, SCHED_FIFO, 0xF);
1584
#else
1585
#ifdef LOWLATENCY
1586 1587 1588
  struct sched_attr attr;
  unsigned int flags = 0;

Raymond Knopp's avatar
 
Raymond Knopp committed
1589 1590 1591 1592
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1593

Raymond Knopp's avatar
 
Raymond Knopp committed
1594 1595
  /* This creates a .5 ms  reservation */
  attr.sched_policy = SCHED_DEADLINE;
1596 1597
  attr.sched_runtime  = 0.2 * 1000000;
  attr.sched_deadline = 0.9 * 1000000;
1598 1599
  attr.sched_period   = 1.0 * 1000000;

Lionel Gauthier's avatar
Lionel Gauthier committed
1600

Raymond Knopp's avatar
 
Raymond Knopp committed
1601 1602 1603 1604
  /* 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");
     }*/
1605

1606
  if (sched_setattr(0, &attr, flags) < 0 ) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1607 1608 1609 1610
    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",
1611
          gettid(),sched_getcpu());
Raymond Knopp's avatar
 
Raymond Knopp committed
1612
  }
1613

1614
#endif
1615 1616
#endif

1617 1618 1619 1620 1621
  // stop early, if an exit is requested
  // FIXME really neccessary?
  if (oai_exit)
    goto eNB_thread_cleanup;

1622
#ifdef RTAI
1623
  printf( "[SCHED][eNB] Started eNB main thread (id %p)\n", task );
Raymond Knopp's avatar
 
Raymond Knopp committed
1624
#else
1625
  printf( "[SCHED][eNB] Started eNB main thread on CPU %d TID %d\n", sched_getcpu(), gettid());
1626 1627 1628
#endif

#ifdef HARD_RT
1629
  rt_make_hard_real_time();
1630 1631
#endif

1632 1633 1634 1635 1636 1637 1638 1639
  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;
1640

1641 1642
  printf( "waiting for sync (eNB_thread)\n" );
  pthread_mutex_lock( &sync_mutex );
1643

1644 1645
  while (sync_var<0)
    pthread_cond_wait( &sync_cond, &sync_mutex );
1646

1647
  pthread_mutex_unlock(&sync_mutex);
1648

1649
  int frame = 0;
1650

1651 1652
  while (!oai_exit) {
    start_meas( &softmodem_stats_mt );
Raymond Knopp's avatar
 
Raymond Knopp committed
1653

1654
#ifdef EXMIMO
1655 1656
    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]);
1657 1658
    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);
1659 1660 1661 1662
    //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];
1663

1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674
    //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;
1675

1676 1677
      if (diff<0)
        diff = diff +150;
1678

1679 1680 1681 1682
      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)))) {
1683

1684 1685 1686 1687
      // 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);
      
1688
      if (exit_missed_slots==1) {
1689 1690
        stop_meas(&softmodem_stats_mt);
        exit_fun("[HW][eNB] missed slot");
1691
      } else {
1692
        num_missed_slots++;
1693
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_MISSED_SLOTS_ENB,num_missed_slots );
1694
      }
1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716

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

    
1717
    }
1718

1719
    if (diff>8)
1720 1721
      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);
1722

1723 1724
    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);
1725 1726

    delay_cnt = 0;
1727

1728 1729 1730 1731
    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);
1732
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP,1);
1733
      ret = rt_sleep_ns(diff*DAQ_PERIOD);
1734 1735
      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);
1736

1737 1738
      if (ret)
        LOG_D(HW,"eNB Frame %d, time %llu: rt_sleep_ns returned %d\n",frame, time_in);
1739

Raymond Knopp's avatar
 
Raymond Knopp committed
1740
      hw_slot = (((((volatile unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15;
1741 1742 1743
      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());
1744
      delay_cnt++;
1745

1746 1747 1748 1749 1750
      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");
      }
1751

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1754
      if ((mbox_current>=135) && (mbox_target<15)) //handle the frame wrap-arround
1755
        diff = 150-mbox_current+mbox_target;
Raymond Knopp's avatar
 
Raymond Knopp committed
1756
      else if ((mbox_current<15) && (mbox_target>=135))
1757
        diff = -150+mbox_target-mbox_current;
Raymond Knopp's avatar
 
Raymond Knopp committed
1758
      else
1759 1760
        diff = mbox_target - mbox_current;
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1761

1762
#else  // EXMIMO
1763 1764
    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 );
1765
    tx_launched = 0;
1766

1767
    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
1768

1769
      unsigned int rxs;
Raymond Knopp's avatar
 
Raymond Knopp committed
1770
#ifndef USRP_DEBUG
1771 1772 1773
      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
1774

1775
      clock_gettime( CLOCK_MONOTONIC, &trx_time0 );
1776

1777 1778 1779
      // 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];
1780

1781
      start_meas( &softmodem_stats_hw );
1782

1783
      openair0_timestamp timestamp;
1784 1785 1786 1787 1788 1789 1790
      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
1791

1792 1793 1794 1795
      if (frame > 10){ 
	if (rxs != spp)
	  exit_fun( "problem receiving samples" );
      }
1796
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
1797

1798
      // Transmit TX buffer based on timestamp from RX
1799
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810

      // 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,
1811
                                1);
Raymond Knopp's avatar
 
Raymond Knopp committed
1812 1813
      }

1814 1815
      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 );
1816 1817 1818 1819

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

1820
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE,0);
1821 1822 1823 1824 1825 1826 1827 1828
#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;
1829

1830
        for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865
          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
1866 1867

#endif // USRP
1868

1869
    if (oai_exit) break;
Raymond Knopp's avatar
 
Raymond Knopp committed
1870

1871 1872 1873 1874 1875
    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;
1876

1877 1878
      if (time_diff < timing_info.time_min)
        timing_info.time_min = time_diff;
1879

1880 1881
      if (time_diff > timing_info.time_max)
        timing_info.time_max = time_diff;
1882

1883 1884 1885 1886 1887 1888
      timing_info.time_avg += time_diff;
    }

    timing_info.n_samples++;

    if ((slot&1) == 1) {
1889
      // odd slot
1890
#ifdef EXMIMO
1891
      int sf = ((slot>>1)+1)%10;
Raymond Knopp's avatar
 
Raymond Knopp committed
1892
#else
1893
      int sf = hw_subframe;
Raymond Knopp's avatar
 
Raymond Knopp committed
1894
#endif
1895 1896

      for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1897 1898
#ifdef EXMIMO

1899 1900
        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);
1901 1902
        } 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);
1903 1904
          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);
1905

1906 1907 1908 1909
          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);
            }
1910
          } else {
1911 1912 1913 1914
            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");
          }
        }
1915

Raymond Knopp's avatar
 
Raymond Knopp committed
1916 1917
#endif

1918 1919 1920 1921 1922
        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
1923

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

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

1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939
        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
1940
      }
1941 1942 1943 1944
    }

#ifdef EXMIMO
    slot++;
1945

1946 1947 1948 1949
    if (slot == 20) {
      frame++;
      slot = 0;
    }
1950

Raymond Knopp's avatar
 
Raymond Knopp committed
1951
#else
1952 1953
    hw_subframe++;
    slot += 2;
1954

1955
    if (hw_subframe == NUM_ENB_THREADS) {
1956
      // the radio frame is complete, start over
1957 1958 1959 1960
      hw_subframe = 0;
      frame++;
      slot = 1;
    }
1961 1962

#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1963

1964
#if defined(ENABLE_ITTI)
1965
    itti_update_lte_time( frame, slot );
1966
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1967
  }
1968 1969

eNB_thread_cleanup:
Raymond Knopp's avatar
 
Raymond Knopp committed
1970
#ifdef DEBUG_THREADS
1971
  printf( "eNB_thread: finished, ran %d times.\n", frame );
Raymond Knopp's avatar
 
Raymond Knopp committed
1972
#endif
1973

1974
#ifdef HARD_RT
Raymond Knopp's avatar
 
Raymond Knopp committed
1975
  rt_make_soft_real_time();
1976 1977
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
1978
#ifdef DEBUG_THREADS
1979
  printf( "Exiting eNB_thread ..." );
Raymond Knopp's avatar
 
Raymond Knopp committed
1980 1981
#endif
  // clean task
1982
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
1983
  rt_task_delete(task);
1984
#endif
1985 1986 1987

  eNB_thread_status = 0;
  return &eNB_thread_status;
Raymond Knopp's avatar
 
Raymond Knopp committed
1988
}
1989

1990

Raymond Knopp's avatar
 
Raymond Knopp committed
1991

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1992

1993 1994
static void get_options (int argc, char **argv)
{
1995 1996 1997
  int c;
  //  char                          line[1000];
  //  int                           l;
1998
  int k,i;//,j,k;
1999
#if defined(OAI_USRP) || defined(CPRIGW)
2000
  int clock_src;
2001
#endif
2002 2003 2004 2005 2006
  int CC_id;
#ifdef EXMIMO
  char rxg_fname[256], line[1000];
  FILE *rxg_fd;
  int l;
2007
#endif
2008 2009 2010



2011 2012

  const Enb_properties_array_t *enb_properties;
2013

2014 2015 2016 2017 2018 2019 2020
  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,
2021
    LONG_OPTION_NO_L2_CONNECT,
Raymond Knopp's avatar
 
Raymond Knopp committed
2022
    LONG_OPTION_CALIB_PRACH_TX,
2023 2024
    LONG_OPTION_RXGAIN,
    LONG_OPTION_TXGAIN,
2025
    LONG_OPTION_SCANCARRIER,
2026 2027 2028
    LONG_OPTION_MAXPOWER,
    LONG_OPTION_DUMP_FRAME,
    LONG_OPTION_LOOPMEMORY
2029
  };
2030

2031 2032 2033 2034 2035 2036 2037
  static const struct option long_options[] = {
    {"ulsch-max-errors",required_argument,  NULL, LONG_OPTION_ULSCH_MAX_CONSECUTIVE_ERRORS},
    {"calib-ue-rx",     required_argument,  NULL, LONG_OPTION_CALIB_UE_RX},
    {"calib-ue-rx-med", required_argument,  NULL, LONG_OPTION_CALIB_UE_RX_MED},
    {"calib-ue-rx-byp", required_argument,  NULL, LONG_OPTION_CALIB_UE_RX_BYP},
    {"debug-ue-prach",  no_argument,        NULL, LONG_OPTION_DEBUG_UE_PRACH},
    {"no-L2-connect",   no_argument,        NULL, LONG_OPTION_NO_L2_CONNECT},
Raymond Knopp's avatar
 
Raymond Knopp committed
2038 2039 2040 2041
    {"calib-prach-tx",   no_argument,        NULL, LONG_OPTION_CALIB_PRACH_TX},
    {"ue-rxgain",   required_argument,  NULL, LONG_OPTION_RXGAIN},
    {"ue-txgain",   required_argument,  NULL, LONG_OPTION_TXGAIN},
    {"ue-scan-carrier",   no_argument,  NULL, LONG_OPTION_SCANCARRIER},
2042
    {"ue-max-power",   required_argument,  NULL, LONG_OPTION_MAXPOWER},
2043 2044
    {"ue-dump-frame", no_argument, NULL, LONG_OPTION_DUMP_FRAME},
    {"loop-memory", required_argument, NULL, LONG_OPTION_LOOPMEMORY},
2045 2046 2047
    {NULL, 0, NULL, 0}
  };

2048
  while ((c = getopt_long (argc, argv, "C:dK:g:F:G:hqO:m:SUVRM:r:P:Ws:t:x:",long_options,NULL)) != -1) {
2049
    switch (c) {
2050 2051 2052 2053 2054
    case LONG_OPTION_MAXPOWER:
      tx_max_power[0]=atoi(optarg);
      for (CC_id=1;CC_id<MAX_NUM_CCs;CC_id++)
	tx_max_power[CC_id]=tx_max_power[0];

2055 2056 2057 2058
    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;
2059

2060 2061 2062 2063 2064
    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;
2065

2066 2067 2068 2069
    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
2070
      break;
2071

2072 2073 2074 2075 2076
    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;
2077

2078 2079 2080
    case LONG_OPTION_DEBUG_UE_PRACH:
      mode = debug_prach;
      break;
2081

2082 2083 2084
    case LONG_OPTION_NO_L2_CONNECT:
      mode = no_L2_connect;
      break;
2085

Raymond Knopp's avatar
 
Raymond Knopp committed
2086 2087 2088 2089
    case LONG_OPTION_CALIB_PRACH_TX:
      mode = calib_prach_tx;
      break;

2090
    case LONG_OPTION_RXGAIN:
2091 2092
      for (i=0; i<4; i++)
        rx_gain[0][i] = atof(optarg);
2093

2094
      break;
2095

2096 2097 2098
    case LONG_OPTION_TXGAIN:
      for (i=0; i<4; i++)
        tx_gain[0][i] = atof(optarg);
2099

2100
      break;
2101

2102 2103 2104 2105 2106
    case LONG_OPTION_SCANCARRIER:
      UE_scan_carrier=1;

      break;

2107 2108 2109 2110 2111 2112 2113 2114 2115 2116
    case LONG_OPTION_LOOPMEMORY:
      mode=loop_through_memory;
      input_fd = fopen(optarg,"r");
      AssertFatal(input_fd != NULL,"Please provide an input file\n");
      break;

   case LONG_OPTION_DUMP_FRAME:
     mode = rx_dump_frame;
     break;

2117 2118 2119
    case 'M':
#ifdef ETHERNET
      strcpy(rrh_eNB_ip,optarg);
2120
#endif
2121
      break;
2122

2123
    case 'C':
2124 2125 2126 2127 2128 2129
      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]);
2130
      }
2131

2132
      UE_scan=0;
2133

2134
      break;
2135

2136 2137 2138 2139
    case 'd':
#ifdef XFORMS
      do_forms=1;
      printf("Running with XFORMS!\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2140
#endif
2141
      break;
2142

2143 2144 2145
    case 'K':
#if defined(ENABLE_ITTI)
      itti_dump_file = strdup(optarg);
2146
#else
2147
      printf("-K option is disabled when ENABLE_ITTI is not defined\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2148
#endif
2149
      break;
2150

2151 2152 2153
    case 'O':
      conf_config_file_name = optarg;
      break;
2154

2155 2156 2157
    case 'U':
      UE_flag = 1;
      break;
2158

2159 2160 2161
    case 'm':
      target_dl_mcs = atoi (optarg);
      break;
2162

2163 2164 2165
    case 't':
      target_ul_mcs = atoi (optarg);
      break;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2166
#ifdef OPENAIR2
2167

2168 2169 2170 2171 2172 2173 2174
    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");
      /*
2175 2176 2177
      if (optarg == NULL){
      in_ip[0] =NULL;
      printf("Enabling OPT for wireshark for local interface");
2178
      } else {
2179 2180 2181
      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);
2182 2183 2184
      }
      */
      break;
2185

2186
    case 'P':
2187 2188
      opt_type = OPT_PCAP;
      opt_enabled=1;
2189 2190 2191 2192 2193

      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");
2194
      } else {
2195 2196 2197
        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);
2198
      }
2199 2200

      break;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2201
#endif
2202

Raymond Knopp's avatar
 
Raymond Knopp committed
2203 2204 2205
    case 'V':
      ouput_vcd = 1;
      break;
2206

Raymond Knopp's avatar
 
Raymond Knopp committed
2207
    case  'q':
Raymond Knopp's avatar
 
Raymond Knopp committed
2208 2209
      opp_enabled = 1;
      break;
2210

Raymond Knopp's avatar
 
Raymond Knopp committed
2211 2212 2213
    case  'R' :
      online_log_messages =1;
      break;
2214

Raymond Knopp's avatar
 
Raymond Knopp committed
2215
    case 'r':
2216
      UE_scan = 0;
2217

2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243
      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
2244
      }
2245

2246
      break;
2247

Raymond Knopp's avatar
 
Raymond Knopp committed
2248
    case 's':
2249
#if defined(OAI_USRP) || defined(CPRIGW)
Raymond Knopp's avatar
 
Raymond Knopp committed
2250 2251

      clock_src = atoi(optarg);
2252

Raymond Knopp's avatar
 
Raymond Knopp committed
2253
      if (clock_src == 0) {
2254 2255 2256 2257 2258
        //  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
2259
      }
2260

Raymond Knopp's avatar
 
Raymond Knopp committed
2261 2262 2263 2264
#else
      printf("Note: -s not defined for ExpressMIMO2\n");
#endif
      break;
2265

2266 2267 2268 2269
    case 'S':
      exit_missed_slots=0;
      printf("Skip exit for missed slots\n");
      break;
2270

2271
    case 'g':
Raymond Knopp's avatar
 
Raymond Knopp committed
2272
      glog_level=atoi(optarg); // value between 1 - 9
2273
      break;
2274 2275

    case 'F':
2276
#ifdef EXMIMO
2277 2278
      sprintf(rxg_fname,"%srxg.lime",optarg);
      rxg_fd = fopen(rxg_fname,"r");
2279

2280
      if (rxg_fd) {
2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298
        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);

2299
#endif
2300
      break;
2301

2302 2303 2304
    case 'G':
      glog_verbosity=atoi(optarg);// value from 0, 0x5, 0x15, 0x35, 0x75
      break;
2305

2306 2307
    case 'x':
      transmission_mode = atoi(optarg);
2308

2309
      if (transmission_mode > 2) {
2310 2311
        printf("Transmission mode > 2 (%d) not supported for the moment\n",transmission_mode);
        exit(-1);
2312
      }
2313

2314
      break;
2315 2316 2317 2318
    case 'h':
      help ();
      exit (-1);
       
Raymond Knopp's avatar
 
Raymond Knopp committed
2319
    default:
2320 2321
      help ();
      exit (-1);
Raymond Knopp's avatar
 
Raymond Knopp committed
2322
      break;
2323 2324
    }
  }
2325

Raymond Knopp's avatar
 
Raymond Knopp committed
2326 2327
  if (UE_flag == 0)
    AssertFatal(conf_config_file_name != NULL,"Please provide a configuration file\n");
2328 2329


Raymond Knopp's avatar
 
Raymond Knopp committed
2330
  if ((UE_flag == 0) && (conf_config_file_name != NULL)) {
2331
    int i,j;
2332

Raymond Knopp's avatar
 
Raymond Knopp committed
2333
    NB_eNB_INST = 1;
2334

Raymond Knopp's avatar
 
Raymond Knopp committed
2335 2336
    /* Read eNB configuration file */
    enb_properties = enb_config_init(conf_config_file_name);
2337

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

Raymond Knopp's avatar
 
Raymond Knopp committed
2342
    /* Update some simulation parameters */
2343
    for (i=0; i < enb_properties->number; i++) {
2344
      AssertFatal (MAX_NUM_CCs == enb_properties->properties[i]->nb_cc,
2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361
                   "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
2362 2363
      }

2364

2365
#ifdef OPENAIR2
2366

2367 2368 2369
      init_all_otg(0);
      g_otg->seed = 0;
      init_seeds(g_otg->seed);
2370 2371 2372 2373 2374 2375 2376 2377 2378 2379

      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");
2380
      }
2381

2382
      init_predef_traffic(enb_properties->properties[i]->num_otg_elements, 1);
2383

2384
#endif
2385

2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399
      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
2400 2401 2402 2403 2404 2405
# 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
2406 2407 2408
#if defined (ENABLE_SECURITY)
      osa_log_level                  = enb_properties->properties[i]->osa_log_level;
      osa_log_verbosity              = enb_properties->properties[i]->osa_log_verbosity;
2409
#endif
Florian Kaltenberger's avatar
Florian Kaltenberger committed
2410

Raymond Knopp's avatar
 
Raymond Knopp committed
2411
      // adjust the log
2412
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
2413 2414 2415 2416 2417 2418 2419 2420 2421 2422
        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
2423
      } // CC_id
2424
    }// i
2425 2426 2427 2428 2429 2430 2431 2432
  } else if (UE_flag == 1) {
    if (conf_config_file_name != NULL) {
      
      // Here the configuration file is the XER encoded UE capabilities
      // Read it in and store in asn1c data structures
      strcpy(uecap_xer,conf_config_file_name);
      uecap_xer_in=1;
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
2433
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
2434
}
2435

2436 2437
int main( int argc, char **argv )
{
Raymond Knopp's avatar
 
Raymond Knopp committed
2438
  int i,aa,card;
Lionel Gauthier's avatar
Lionel Gauthier committed
2439
#if defined (XFORMS) || defined (EMOS) || defined (EXMIMO)
Raymond Knopp's avatar
 
Raymond Knopp committed
2440
  void *status;
2441
#endif
2442

Raymond Knopp's avatar
 
Raymond Knopp committed
2443
  int CC_id;
Raymond Knopp's avatar
 
Raymond Knopp committed
2444
  uint16_t Nid_cell = 0;
2445
  uint8_t  cooperation_flag=0,  abstraction_flag=0;
2446
#ifndef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
2447
  uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2;
2448 2449 2450
#endif

#ifdef ENABLE_TCXO
Raymond Knopp's avatar
 
Raymond Knopp committed
2451
  unsigned int tcxo = 114;
2452 2453
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
2454
#if defined (XFORMS)
2455 2456
  int ret;
#endif
2457
#if defined (EMOS) || (! defined (RTAI))
Raymond Knopp's avatar
 
Raymond Knopp committed
2458
  int error_code;
2459
#endif
2460

2461 2462 2463 2464 2465
#ifdef DEBUG_CONSOLE
  setvbuf(stdout, NULL, _IONBF, 0);
  setvbuf(stderr, NULL, _IONBF, 0);
#endif

2466 2467 2468
  PHY_VARS_UE *UE[MAX_NUM_CCs];

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

2471
  memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
Raymond Knopp's avatar
 
Raymond Knopp committed
2472
  set_latency_target();
2473

2474

2475

2476
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2477 2478
    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 */
2479
    frame_parms[CC_id]->frame_type         = FDD; /* TDD */
Raymond Knopp's avatar
 
Raymond Knopp committed
2480 2481
    frame_parms[CC_id]->tdd_config          = 3;
    frame_parms[CC_id]->tdd_config_S        = 0;
2482 2483
    frame_parms[CC_id]->N_RB_DL             = 100;
    frame_parms[CC_id]->N_RB_UL             = 100;
Raymond Knopp's avatar
 
Raymond Knopp committed
2484
    frame_parms[CC_id]->Ncp                 = NORMAL;
Raymond Knopp's avatar
 
Raymond Knopp committed
2485 2486
    frame_parms[CC_id]->Ncp_UL              = NORMAL;
    frame_parms[CC_id]->Nid_cell            = Nid_cell;
Raymond Knopp's avatar
 
Raymond Knopp committed
2487
    frame_parms[CC_id]->num_MBSFN_config    = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2488 2489 2490
    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
2491
  }
2492

2493 2494 2495 2496 2497
  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];
2498
    //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
2499
  }
2500 2501
  logInit();
 
2502
  get_options (argc, argv); //Command-line options
2503 2504 2505
 
  
  // initialize the log (see log.h for details)
Florian Kaltenberger's avatar
Florian Kaltenberger committed
2506 2507
  set_glog(glog_level, glog_verbosity);

2508 2509
  //randominit (0);
  set_taus_seed (0);
Raymond Knopp's avatar
 
Raymond Knopp committed
2510

2511 2512
  if (UE_flag==1) {
    printf("configuring for UE\n");
2513

2514
    set_comp_log(HW,      LOG_INFO,  LOG_HIGH, 1);
2515 2516 2517 2518 2519 2520
    set_comp_log(PHY,     LOG_INFO,   LOG_HIGH, 1);
    set_comp_log(MAC,     LOG_INFO,   LOG_HIGH, 1);
    set_comp_log(RLC,     LOG_INFO,   LOG_HIGH, 1);
    set_comp_log(PDCP,    LOG_INFO,   LOG_HIGH, 1);
    set_comp_log(OTG,     LOG_INFO,   LOG_HIGH, 1);
    set_comp_log(RRC,     LOG_INFO,   LOG_HIGH, 1);
2521
#if defined(ENABLE_ITTI)
2522
    set_comp_log(EMU,     LOG_INFO,   LOG_MED, 1);
2523
# if defined(ENABLE_USE_MME)
2524
    set_comp_log(NAS,     LOG_INFO,   LOG_HIGH, 1);
2525 2526
# endif
#endif
2527 2528
  } else {
    printf("configuring for eNB\n");
2529

2530
    set_comp_log(HW,      hw_log_level, hw_log_verbosity, 1);
2531
#ifdef OPENAIR2
2532 2533 2534 2535 2536
    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);

2537
#else
2538
    set_comp_log(PHY,     LOG_INFO,   LOG_HIGH, 1);
2539
#endif
2540 2541 2542 2543
    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);
2544
#if defined(ENABLE_ITTI)
2545
    set_comp_log(EMU,     LOG_INFO,   LOG_MED, 1);
2546
# if defined(ENABLE_USE_MME)
2547 2548 2549 2550
    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);
2551
# endif
2552
#if defined(ENABLE_SECURITY)
2553
    set_comp_log(OSA,    osa_log_level,   osa_log_verbosity, 1);
2554
#endif
2555
#endif
2556
#ifdef LOCALIZATION
2557 2558 2559 2560 2561 2562 2563 2564 2565
    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
2566
    }
2567
  }
2568

Raymond Knopp's avatar
 
Raymond Knopp committed
2569 2570
  if (ouput_vcd) {
    if (UE_flag==1)
2571
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_UE.vcd");
Raymond Knopp's avatar
 
Raymond Knopp committed
2572
    else
2573
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_eNB.vcd");
Raymond Knopp's avatar
 
Raymond Knopp committed
2574
  }
2575

2576 2577
  if (opp_enabled ==1)
    reset_opp_meas();
2578

2579
#if defined(ENABLE_ITTI)
2580

Raymond Knopp's avatar
 
Raymond Knopp committed
2581 2582
  if (UE_flag == 1) {
    log_set_instance_type (LOG_INSTANCE_UE);
2583
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
2584 2585
    log_set_instance_type (LOG_INSTANCE_ENB);
  }
2586

Raymond Knopp's avatar
 
Raymond Knopp committed
2587
  itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, itti_dump_file);
2588
#endif
2589 2590 2591
  // initialize mscgen log after ITTI
  MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX);

2592
#ifdef OPENAIR2
2593

2594 2595
  if (opt_type != OPT_NONE) {
    radio_type_t radio_type;
2596

2597 2598
    if (frame_parms[0]->frame_type == FDD)
      radio_type = RADIO_TYPE_FDD;
2599
    else
2600
      radio_type = RADIO_TYPE_TDD;
2601

2602 2603 2604
    if (init_opt(in_path, in_ip, NULL, radio_type) == -1)
      LOG_E(OPT,"failed to run OPT \n");
  }
2605

2606
#endif
2607
#ifdef PDCP_USE_NETLINK
Raymond Knopp's avatar
 
Raymond Knopp committed
2608
  netlink_init();
2609 2610
#endif

2611
#if !defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
2612 2613 2614
  // to make a graceful exit when ctrl-c is pressed
  signal(SIGSEGV, signal_handler);
  signal(SIGINT, signal_handler);
2615
#endif
2616 2617

#ifndef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
2618 2619 2620 2621
  check_clock();
#endif

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

2625 2626 2627 2628 2629 2630 2631 2632 2633
    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
2634 2635 2636 2637 2638 2639 2640 2641
    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;
2642 2643
    init_ul_hopping(frame_parms[CC_id]);
    init_frame_parms(frame_parms[CC_id],1);
2644 2645
    //   phy_init_top(frame_parms[CC_id]);
    phy_init_lte_top(frame_parms[CC_id]);
Raymond Knopp's avatar
 
Raymond Knopp committed
2646 2647 2648
  }


2649
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2650
    //init prach for openair1 test
2651
    frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22;
Raymond Knopp's avatar
 
Raymond Knopp committed
2652
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1;
2653
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2654 2655 2656
    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
2657
    // N_ZC = (prach_fmt <4)?839:139;
Raymond Knopp's avatar
 
Raymond Knopp committed
2658
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
2659 2660

  if (UE_flag==1) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2661 2662 2663
    NB_UE_INST=1;
    NB_INST=1;

Raymond Knopp's avatar
 
Raymond Knopp committed
2664 2665
    PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE**));
    PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_UE*)*MAX_NUM_CCs);
2666 2667

    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
2668 2669 2670 2671

      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
2672
#ifndef OPENAIR2
2673 2674 2675 2676 2677 2678 2679 2680 2681

      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
2682
      }
2683

2684
#endif
2685 2686 2687


      UE[CC_id]->UE_scan = UE_scan;
2688
      UE[CC_id]->UE_scan_carrier = UE_scan_carrier;
2689 2690 2691
      UE[CC_id]->mode    = mode;

      compute_prach_seq(&UE[CC_id]->lte_frame_parms.prach_config_common,
2692 2693 2694
                        UE[CC_id]->lte_frame_parms.frame_type,
                        UE[CC_id]->X_u);

2695
      UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1234;
2696
#ifndef OPENAIR2
2697
      UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1235;
2698
#endif
2699

2700
#ifdef EXMIMO
2701

2702 2703 2704 2705
      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
2706
      }
2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725

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

2728
#else
2729
      UE[CC_id]->rx_total_gain_dB =  (int)rx_gain[CC_id][0];
2730
#endif
2731

2732
      UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id];
2733

2734 2735


2736
#ifdef EXMIMO
2737

Raymond Knopp's avatar
 
Raymond Knopp committed
2738
      //N_TA_offset
2739
      if (UE[CC_id]->lte_frame_parms.frame_type == TDD) {
2740 2741 2742 2743 2744 2745 2746 2747
        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
2748
      }
2749

2750
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
2751
      //already taken care of in lte-softmodem
2752
      UE[CC_id]->N_TA_offset = 0;
2753
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2754
    }
2755

Raymond Knopp's avatar
 
Raymond Knopp committed
2756 2757 2758 2759
    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;
2760 2761 2762



Raymond Knopp's avatar
 
Raymond Knopp committed
2763
    //  printf("tx_max_power = %d -> amp %d\n",tx_max_power,get_tx_amp(tx_max_power,tx_max_power));
2764 2765 2766 2767 2768 2769 2770 2771 2772
  } 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;

2773
#ifndef OPENAIR2
2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789

      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
2790

2791
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
2792

2793
      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
2794

2795
#else
2796 2797 2798
      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
2799

2800 2801 2802
      // 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
2803

2804
#endif
2805

2806
#ifdef EXMIMO
2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817

      //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
2818
      }
2819

2820 2821 2822 2823
#else
      //already taken care of in lte-softmodem
      PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 0;
#endif
2824

2825
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
2826 2827


2828 2829 2830 2831 2832 2833 2834 2835 2836
    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;

  }
2837

2838

Raymond Knopp's avatar
 
Raymond Knopp committed
2839
  dump_frame_parms(frame_parms[0]);
2840

Raymond Knopp's avatar
 
Raymond Knopp committed
2841
  if(frame_parms[0]->N_RB_DL == 100) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2842
    sample_rate = 30.72e6;
2843
    bw          = 10.0e6;
2844
#ifndef EXMIMO
2845
    openair0_cfg[0].samples_per_packet = 2048;
2846 2847 2848
    samples_per_frame = 307200; 
    openair0_cfg[card].tx_bw = 10e6;
    openair0_cfg[card].rx_bw = 10e6;
Raymond Knopp's avatar
 
Raymond Knopp committed
2849 2850
    // from usrp_time_offset
    tx_forward_nsamps = 175;
2851
    tx_delay = 8;
Raymond Knopp's avatar
 
Raymond Knopp committed
2852
#endif
2853
  } else if(frame_parms[0]->N_RB_DL == 50) {
2854
    sample_rate = 15.36e6;
2855
    bw          = 5.0e6;
2856
#ifndef EXMIMO
2857
    openair0_cfg[0].samples_per_packet = 2048;
Raymond Knopp's avatar
 
Raymond Knopp committed
2858
    samples_per_frame = 153600;
2859 2860
    openair0_cfg[card].tx_bw = 5e6;
    openair0_cfg[card].rx_bw = 5e6;
Raymond Knopp's avatar
 
Raymond Knopp committed
2861
    tx_forward_nsamps = 95;
2862
    tx_delay = 5;
Raymond Knopp's avatar
 
Raymond Knopp committed
2863
#endif
2864
  } else if (frame_parms[0]->N_RB_DL == 25) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2865
    sample_rate = 7.68e6;
2866
    bw          = 2.5e6;
2867
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
2868
    samples_per_frame = 76800;
2869 2870 2871 2872 2873 2874 2875
    openair0_cfg[card].tx_bw = 2.5e6;
    openair0_cfg[card].rx_bw = 2.5e6;
    openair0_cfg[0].samples_per_packet = 1024;
#ifdef OAI_USRP
    tx_forward_nsamps = 70;
    tx_delay = 6;
#elif OAI_BLADERF
Raymond Knopp's avatar
 
Raymond Knopp committed
2876
    tx_forward_nsamps = 70;
2877
    tx_delay = 6;
2878
#endif 
Raymond Knopp's avatar
 
Raymond Knopp committed
2879
#endif
2880
  } else if (frame_parms[0]->N_RB_DL == 6) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2881
    sample_rate = 1.92e6;
2882
    bw          = 0.96e6;
Raymond Knopp's avatar
 
Raymond Knopp committed
2883
#ifndef EXMIMO
2884
    openair0_cfg[0].samples_per_packet = 256;
Raymond Knopp's avatar
 
Raymond Knopp committed
2885
    samples_per_frame = 19200;
2886 2887
    openair0_cfg[card].tx_bw = 1.5e6;
    openair0_cfg[card].rx_bw = 1.5e6;
Raymond Knopp's avatar
 
Raymond Knopp committed
2888
    tx_forward_nsamps = 40;
2889
    tx_delay = 8;
Raymond Knopp's avatar
 
Raymond Knopp committed
2890 2891
#endif
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
2892 2893

#ifdef ETHERNET
2894

thomasl's avatar
thomasl committed
2895
  if (frame_parms[0]->N_RB_DL == 6) openair0_cfg[0].samples_per_packet = 256;
2896
  else openair0_cfg[0].samples_per_packet = 1024;
Raymond Knopp's avatar
 
Raymond Knopp committed
2897

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

2901

2902
  for (card=0; card<MAX_CARDS; card++) {
2903
#ifndef EXMIMO
2904
    openair0_cfg[card].samples_per_packet = openair0_cfg[0].samples_per_packet;
2905 2906
#endif
    printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card,
2907 2908
           ((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
2909 2910
    openair0_cfg[card].Mod_id = 0;
#ifdef ETHERNET
2911 2912

    if (UE_flag) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2913 2914 2915
      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;
2916 2917 2918 2919
    } 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
2920
    }
2921

Raymond Knopp's avatar
 
Raymond Knopp committed
2922
#endif
2923 2924 2925
    openair0_cfg[card].sample_rate = sample_rate;
    openair0_cfg[card].tx_bw = bw;
    openair0_cfg[card].rx_bw = bw;
2926
    // in the case of the USRP, the following variables need to be initialized before the init
2927
    // since the USRP only supports one CC (for the moment), we initialize all the cards with first CC.
2928
    // in the case of EXMIMO2, these values are overwirtten in the function setup_eNB/UE_buffer
2929
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
2930 2931
    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));
2932 2933

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

2935
      openair0_cfg[card].autocal[i] = 1;
2936
      openair0_cfg[card].tx_gain[i] = tx_gain[0][i];
2937
      openair0_cfg[card].rx_gain[i] = ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->rx_total_gain_eNB_dB :
2938
                                       PHY_vars_UE_g[0][0]->rx_total_gain_dB) - USRP_GAIN_OFFSET;  // calibrated for USRP B210 @ 2.6 GHz, 30.72 MS/s
2939

2940 2941
      switch(frame_parms[0]->N_RB_DL) {
      case 6:
2942 2943 2944
        openair0_cfg[card].rx_gain[i] -= 6;
        break;

2945
      case 25:
2946 2947 2948
        openair0_cfg[card].rx_gain[i] += 6;
        break;

2949
      case 50:
2950 2951 2952
        openair0_cfg[card].rx_gain[i] += 8;
        break;

2953
      default:
2954
        break;
2955
      }
2956

2957 2958
      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];
2959
      printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n",
2960 2961 2962 2963 2964
             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
2965
    }
2966

2967
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2968
  }
2969

2970
  printf("Initializing openair0 ...");
2971
  openair0_cfg[0].log_level = glog_level;
2972

2973 2974 2975

  if ((mode!=loop_through_memory) && 
      (openair0_device_init(&openair0, &openair0_cfg[0]) <0)) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2976 2977 2978
    printf("Exiting, cannot initialize device\n");
    exit(-1);
  }
2979 2980 2981
  else if (mode==loop_through_memory) {
    
  }
2982

2983
  printf("Done\n");
2984 2985 2986

  mac_xface = malloc(sizeof(MAC_xface));

2987
#ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
2988
  int eMBMS_active=0;
2989

Raymond Knopp's avatar
 
Raymond Knopp committed
2990
  l2_init(frame_parms[0],eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL,
2991 2992 2993 2994
          0,// cba_group_active
          0); // HO flag


2995 2996
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
2997
  mac_xface->macphy_exit = &exit_fun;
2998

winckel's avatar
winckel committed
2999
#if defined(ENABLE_ITTI)
3000

Raymond Knopp's avatar
 
Raymond Knopp committed
3001
  if (create_tasks(UE_flag ? 0 : 1, UE_flag ? 1 : 0) < 0) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3002
    printf("cannot create ITTI tasks\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3003 3004
    exit(-1); // need a softer mode
  }
3005

Raymond Knopp's avatar
 
Raymond Knopp committed
3006
  printf("ITTI tasks created\n");
winckel's avatar
winckel committed
3007
#endif
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3008 3009

#ifdef OPENAIR2
3010
  if (UE_flag==1) {
3011
    printf("Filling UE band info\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3012
    fill_ue_band_info();
3013
    mac_xface->dl_phy_sync_success (0, 0, 0, 1);
3014
  } else
3015
    mac_xface->mrbch_phy_sync_failure (0, 0, 0);
3016

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3017
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3018

3019
  /* #ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
3020 3021 3022 3023 3024 3025
  //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
3026 3027 3028 3029 3030 3031
  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
3032 3033 3034
  }
  init_predef_traffic(UE_flag ? 1 : 0, UE_flag ? 0 : 1);
  //  }
3035
  #endif */
Raymond Knopp's avatar
 
Raymond Knopp committed
3036

3037
#ifdef EXMIMO
3038
  number_of_cards = openair0_num_detected_cards;
3039 3040
#else
  number_of_cards = 1;
3041
#endif
3042

3043

3044

3045
  for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3046
    rf_map[CC_id].card=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3047
    rf_map[CC_id].chain=CC_id;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3048
  }
3049

Raymond Knopp's avatar
 
Raymond Knopp committed
3050 3051
  // connect the TX/RX buffers
  if (UE_flag==1) {
3052 3053 3054
#ifdef OAI_USRP
    openair_daq_vars.timing_advance = 160;
#else
3055
    openair_daq_vars.timing_advance = 160;
3056
#endif
3057
    if (setup_ue_buffers(UE,&openair0_cfg[0],rf_map)!=0) {
3058 3059 3060
      printf("Error setting up eNB buffer\n");
      exit(-1);
    }
3061

3062
    printf("Setting UE buffer to all-RX\n");
3063

3064
    // Set LSBs for antenna switch (ExpressMIMO)
3065
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3066
      for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++)
3067 3068
        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
3069
    }
3070

3071 3072 3073 3074 3075 3076 3077
    if (input_fd) {
      printf("Reading in from file to antenna buffer %d\n",0);
      fread(UE[0]->lte_ue_common_vars.rxdata[0],
	    sizeof(int32_t),
	    frame_parms[0]->samples_per_tti*10,
	    input_fd);
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3078
    //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX;
3079
  } else {
3080
    openair_daq_vars.timing_advance = 0;
3081

3082 3083 3084 3085
    if (setup_eNB_buffers(PHY_vars_eNB_g[0],&openair0_cfg[0],rf_map)!=0) {
      printf("Error setting up eNB buffer\n");
      exit(-1);
    }
3086

3087
    printf("Setting eNB buffer to all-RX\n");
3088

3089
    // Set LSBs for antenna switch (ExpressMIMO)
3090
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3091
      for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++)
3092 3093
        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
3094
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3095
  }
3096

3097
#ifdef EXMIMO
3098
  openair0_config(&openair0_cfg[0],UE_flag);
Raymond Knopp's avatar
 
Raymond Knopp committed
3099 3100
#endif

3101
  /*
Raymond Knopp's avatar
 
Raymond Knopp committed
3102 3103
      for (ant=0;ant<4;ant++)
      p_exmimo_config->rf.do_autocal[ant] = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3104
  */
3105 3106

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3109 3110 3111 3112 3113 3114
  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);
3115
  else
Raymond Knopp's avatar
 
Raymond Knopp committed
3116
    printf("[OPENAIR][SCHED][INIT] Problem creating EMOS FIFO %d, error_code %d\n",CHANSOUNDER_FIFO_MINOR,error_code);
3117

3118 3119
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3120
  mlockall(MCL_CURRENT | MCL_FUTURE);
3121 3122

#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3123
  // make main thread LXRT soft realtime
3124
  /* task = */ rt_task_init_schmod(nam2num("MAIN"), 9, 0, 0, SCHED_FIFO, 0xF);
Raymond Knopp's avatar
 
Raymond Knopp committed
3125 3126 3127 3128 3129

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3132 3133
  pthread_cond_init(&sync_cond,NULL);
  pthread_mutex_init(&sync_mutex, NULL);
3134

3135
#if defined(ENABLE_ITTI)
3136

Florian Kaltenberger's avatar
Florian Kaltenberger committed
3137 3138 3139 3140 3141
  // 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);
  }
3142

3143
#endif
3144

Raymond Knopp's avatar
 
Raymond Knopp committed
3145 3146

  // this starts the DMA transfers
3147
#ifdef EXMIMO
3148

Raymond Knopp's avatar
 
Raymond Knopp committed
3149
  if (UE_flag!=1)
3150
    for (card=0; card<openair0_num_detected_cards; card++)
3151
      openair0_start_rt_acquisition(card);
3152

Raymond Knopp's avatar
 
Raymond Knopp committed
3153
#endif
3154 3155

#ifdef XFORMS
3156 3157
  int UE_id;

Raymond Knopp's avatar
 
Raymond Knopp committed
3158 3159
  if (do_forms==1) {
    fl_initialize (&argc, argv, NULL, 0, 0);
3160 3161

    if (UE_flag==0) {
3162
      form_stats_l2 = create_form_stats_form();
3163 3164 3165
      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");
3166 3167

      for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180
	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");
	  }
	}
3181
      }
3182
    } else {
3183 3184 3185 3186 3187 3188 3189
      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
3190
      if (openair_daq_vars.use_ia_receiver) {
3191 3192 3193 3194 3195
        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
3196 3197 3198
      }
    }

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

3201 3202
    if (ret == 0)
      pthread_setname_np( forms_thread, "xforms" );
3203

Raymond Knopp's avatar
 
Raymond Knopp committed
3204 3205
    printf("Scope thread created, ret=%d\n",ret);
  }
3206

3207 3208 3209
#endif

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3210 3211
  ret = pthread_create(&thread3, NULL, emos_thread, NULL);
  printf("EMOS thread created, ret=%d\n",ret);
jiangx's avatar
jiangx committed
3212 3213
  ret = pthread_create(&thread4, NULL, gps_thread, NULL);
  printf("GPS thread created, ret=%d\n",ret);
3214 3215
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3216
  rt_sleep_ns(10*FRAME_PERIOD);
3217 3218

#ifndef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3219
  pthread_attr_init (&attr_dlsch_threads);
3220
  pthread_attr_setstacksize(&attr_dlsch_threads,4*PTHREAD_STACK_MIN);
3221

3222
  pthread_attr_init (&attr_UE_thread);
3223
  pthread_attr_setstacksize(&attr_UE_thread,8192);//5*PTHREAD_STACK_MIN);
3224

3225
#ifndef LOWLATENCY
3226 3227
  sched_param_UE_thread.sched_priority = sched_get_priority_max(SCHED_FIFO);
  pthread_attr_setschedparam(&attr_UE_thread,&sched_param_UE_thread);
3228
  sched_param_dlsch.sched_priority = sched_get_priority_max(SCHED_FIFO); //OPENAIR_THREAD_PRIORITY;
Raymond Knopp's avatar
 
Raymond Knopp committed
3229 3230
  pthread_attr_setschedparam  (&attr_dlsch_threads, &sched_param_dlsch);
  pthread_attr_setschedpolicy (&attr_dlsch_threads, SCHED_FIFO);
3231
  printf("Setting eNB_thread FIFO scheduling policy with priority %d \n", sched_param_dlsch.sched_priority);
3232
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3233

3234 3235
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3236 3237
  // start the main thread
  if (UE_flag == 1) {
3238
    printf("Intializing UE Threads ...\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3239
    init_UE_threads();
3240 3241 3242 3243 3244
#ifdef DLSCH_THREAD
    init_rx_pdsch_thread();
    rt_sleep_ns(FRAME_PERIOD/10);
    init_dlsch_threads();
#endif
3245

3246
    sleep(1);
3247
#ifdef RTAI
3248
    main_ue_thread = rt_thread_create(UE_thread, NULL, 100000000);
3249
#else
3250
    error_code = pthread_create(&main_ue_thread, &attr_UE_thread, UE_thread, NULL);
3251

Raymond Knopp's avatar
 
Raymond Knopp committed
3252 3253 3254
    if (error_code!= 0) {
      LOG_D(HW,"[lte-softmodem.c] Could not allocate UE_thread, error %d\n",error_code);
      return(error_code);
3255
    } else {
3256 3257
      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
3258
    }
3259

3260
#endif
3261
    printf("UE threads created\n");
3262
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
3263 3264
    if (multi_thread>0) {
      init_eNB_proc();
3265
      sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3266 3267
      LOG_D(HW,"[lte-softmodem.c] eNB threads created\n");
    }
3268

3269
    printf("Creating main eNB_thread \n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3270
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3271
    main_eNB_thread = rt_thread_create(eNB_thread, NULL, PTHREAD_STACK_MIN);
Raymond Knopp's avatar
 
Raymond Knopp committed
3272
#else
3273
    error_code = pthread_create( &main_eNB_thread, &attr_dlsch_threads, eNB_thread, NULL );
3274

Raymond Knopp's avatar
 
Raymond Knopp committed
3275 3276 3277
    if (error_code!= 0) {
      LOG_D(HW,"[lte-softmodem.c] Could not allocate eNB_thread, error %d\n",error_code);
      return(error_code);
3278
    } else {
3279 3280
      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
3281
    }
3282

Raymond Knopp's avatar
 
Raymond Knopp committed
3283 3284
#endif
  }
3285

Raymond Knopp's avatar
 
Raymond Knopp committed
3286
  // Sleep to allow all threads to setup
Raymond Knopp's avatar
 
Raymond Knopp committed
3287
  sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3288

3289
#ifdef USE_MME
3290

3291 3292 3293
  while (start_UE == 0) {
    sleep(1);
  }
3294

3295 3296
#endif

3297
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3298
#ifndef USRP_DEBUG
3299 3300
  if (mode!=loop_through_memory)
    openair0.trx_start_func(&openair0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3301
  //  printf("returning from usrp start streaming: %llu\n",get_usrp_time(&openair0));
Raymond Knopp's avatar
 
Raymond Knopp committed
3302
#endif
3303 3304
#endif

3305

Raymond Knopp's avatar
 
Raymond Knopp committed
3306
  pthread_mutex_lock(&sync_mutex);
3307
  sync_var=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3308 3309
  pthread_cond_broadcast(&sync_cond);
  pthread_mutex_unlock(&sync_mutex);
3310

Raymond Knopp's avatar
 
Raymond Knopp committed
3311 3312 3313
  // wait for end of program
  printf("TYPE <CTRL-C> TO TERMINATE\n");
  //getchar();
3314 3315

#if defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
3316 3317
  printf("Entering ITTI signals handler\n");
  itti_wait_tasks_end();
3318
  oai_exit=1;
3319
#else
3320

Raymond Knopp's avatar
 
Raymond Knopp committed
3321 3322
  while (oai_exit==0)
    rt_sleep_ns(FRAME_PERIOD);
3323

3324
#endif
3325

Raymond Knopp's avatar
 
Raymond Knopp committed
3326
  // stop threads
3327
#ifdef XFORMS
Raymond Knopp's avatar
 
Raymond Knopp committed
3328
  printf("waiting for XFORMS thread\n");
3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342

  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++) {
3343 3344 3345 3346
	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
3347
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
3348
    }
3349 3350
  }

3351 3352
#endif

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3355 3356
  // cleanup
  if (UE_flag == 1) {
3357
#ifdef EXMIMO
3358
#ifdef RTAI
3359
    rt_thread_join(main_ue_thread);
3360
#else
3361
    pthread_join(main_ue_thread,&status);
3362 3363
#endif
#ifdef DLSCH_THREAD
Raymond Knopp's avatar
 
Raymond Knopp committed
3364 3365
    cleanup_dlsch_threads();
    cleanup_rx_pdsch_thread();
3366
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3367
#endif
3368
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
3369
#ifdef DEBUG_THREADS
Raymond Knopp's avatar
 
Raymond Knopp committed
3370
    printf("Joining eNB_thread ...");
Raymond Knopp's avatar
 
Raymond Knopp committed
3371
#endif
3372
#ifdef RTAI
3373
    rt_thread_join(main_eNB_thread);
3374
#else
3375 3376
    int *eNB_thread_status_p;
    int result = pthread_join( main_eNB_thread, (void**)&eNB_thread_status_p );
Raymond Knopp's avatar
 
Raymond Knopp committed
3377
#ifdef DEBUG_THREADS
3378

3379
    if (result != 0) {
3380
      printf( "\nError joining main_eNB_thread.\n" );
3381
    } else {
3382 3383 3384 3385 3386
      if (eNB_thread_status_p) {
        printf( "status %d\n", *eNB_thread_status_p );
      } else {
        printf( "The thread was killed. No status available.\n");
      }
3387
    }
3388

3389 3390
#else
    UNUSED(result);
3391 3392
#endif // DEBUG_THREADS
#endif // RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3393

Raymond Knopp's avatar
 
Raymond Knopp committed
3394 3395 3396
    if (multi_thread>0) {
      printf("Killing eNB processing threads\n");
      kill_eNB_proc();
Raymond Knopp's avatar
 
Raymond Knopp committed
3397

Raymond Knopp's avatar
 
Raymond Knopp committed
3398
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3399
  }
3400

3401
#ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
3402
  //cleanup_pdcp_thread();
3403 3404
#endif

3405
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3406
  stop_rt_timer();
3407
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3408 3409
  pthread_cond_destroy(&sync_cond);
  pthread_mutex_destroy(&sync_mutex);
3410

3411

3412
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3413
  printf("stopping card\n");
3414
  openair0_stop(0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3415 3416
  printf("closing openair0_lib\n");
  openair0_close();
Raymond Knopp's avatar
 
Raymond Knopp committed
3417
#endif
3418 3419

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3420 3421 3422
  printf("waiting for EMOS thread\n");
  pthread_cancel(thread3);
  pthread_join(thread3,&status);
jiangx's avatar
jiangx committed
3423 3424 3425
  printf("waiting for GPS thread\n");
  pthread_cancel(thread4);
  pthread_join(thread4,&status);
3426 3427 3428
#endif

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3429 3430
  error_code = rtf_destroy(CHANSOUNDER_FIFO_MINOR);
  printf("[OPENAIR][SCHED][CLEANUP] EMOS FIFO closed, error_code %d\n", error_code);
3431 3432
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3433
  if (ouput_vcd)
3434
    VCD_SIGNAL_DUMPER_CLOSE();
3435

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3436
#ifdef OPENAIR2
3437

3438
  if (opt_enabled == 1)
3439
    terminate_opt();
3440

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3441
#endif
3442

Raymond Knopp's avatar
 
Raymond Knopp committed
3443
  logClean();
3444

Raymond Knopp's avatar
 
Raymond Knopp committed
3445 3446
  return 0;
}
3447 3448


3449 3450 3451
/* 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
3452
   antennas are mapped to successive RF chains on the same card. */
3453 3454
int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs])
{
3455

3456
  int i, CC_id;
3457
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3458
  uint16_t N_TA_offset = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3459 3460
#else
  int j;
Raymond Knopp's avatar
 
Raymond Knopp committed
3461
#endif
3462
  LTE_DL_FRAME_PARMS *frame_parms;
3463

Raymond Knopp's avatar
 
Raymond Knopp committed
3464

3465 3466
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    if (phy_vars_eNB[CC_id]) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3467 3468
      frame_parms = &(phy_vars_eNB[CC_id]->lte_frame_parms);
      printf("setup_eNB_buffers: frame_parms = %p\n",frame_parms);
3469
    } else {
3470 3471
      printf("phy_vars_eNB[%d] not initialized\n", CC_id);
      return(-1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3472
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3473

3474
#ifndef EXMIMO
3475

3476 3477
    if (frame_parms->frame_type == TDD) {
      if (frame_parms->N_RB_DL == 100)
3478
        N_TA_offset = 624;
3479
      else if (frame_parms->N_RB_DL == 50)
3480
        N_TA_offset = 624/2;
3481
      else if (frame_parms->N_RB_DL == 25)
3482
        N_TA_offset = 624/4;
Raymond Knopp's avatar
 
Raymond Knopp committed
3483
    }
3484

Raymond Knopp's avatar
 
Raymond Knopp committed
3485
#endif
3486 3487


3488 3489 3490



Raymond Knopp's avatar
 
Raymond Knopp committed
3491
    // replace RX signal buffers with mmaped HW versions
3492
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3493 3494 3495
    openair0_cfg[CC_id].tx_num_channels = 0;
    openair0_cfg[CC_id].rx_num_channels = 0;

3496
    for (i=0; i<frame_parms->nb_antennas_rx; i++) {
3497 3498 3499
      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];
3500

3501
      if (openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i]) {
3502 3503 3504 3505 3506 3507
        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++;
3508
      }
3509

3510
      printf("rxdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]);
3511 3512 3513 3514

      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;
3515
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
3516
    }
3517 3518

    for (i=0; i<frame_parms->nb_antennas_tx; i++) {
3519 3520 3521
      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];
3522

3523
      if (openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i]) {
3524 3525 3526 3527 3528 3529
        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++;
3530
      }
3531

3532
      printf("txdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3533 3534 3535 3536

      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;
3537
      }
3538
    }
3539

3540
#else // not EXMIMO
3541 3542 3543
    rxdata = (int32_t**)malloc16(frame_parms->nb_antennas_rx*sizeof(int32_t*));
    txdata = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*));

3544
    for (i=0; i<frame_parms->nb_antennas_rx; i++) {
3545
      free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]);
3546 3547
      rxdata[i] = (int32_t*)(16 + malloc16(16+samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation
      phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i] = rxdata[i]-N_TA_offset; // N_TA offset for TDD         FIXME! N_TA_offset > 16 => access of unallocated memory
3548 3549
      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
3550
    }
3551 3552

    for (i=0; i<frame_parms->nb_antennas_tx; i++) {
3553
      free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3554
      txdata[i] = (int32_t*)(16 + malloc16(16 + samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation
3555 3556
      phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i] = txdata[i];
      memset(txdata[i], 0, samples_per_frame*sizeof(int32_t));
3557
      printf("txdata[%d] @ %p\n", i, phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3558

Raymond Knopp's avatar
 
Raymond Knopp committed
3559
    }
3560

Raymond Knopp's avatar
 
Raymond Knopp committed
3561
#endif
3562
  }
3563

3564
  return(0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3565
}
3566

3567 3568
void reset_opp_meas(void)
{
3569 3570 3571
  int sfn;
  reset_meas(&softmodem_stats_mt);
  reset_meas(&softmodem_stats_hw);
3572

3573 3574 3575 3576 3577 3578
  for (sfn=0; sfn < 10; sfn++) {
    reset_meas(&softmodem_stats_tx_sf[sfn]);
    reset_meas(&softmodem_stats_rx_sf[sfn]);
  }
}

3579 3580
void print_opp_meas(void)
{
3581 3582 3583
  int sfn=0;
  print_meas(&softmodem_stats_mt, "Main ENB Thread", NULL, NULL);
  print_meas(&softmodem_stats_hw, "HW Acquisation", NULL, NULL);
3584

3585 3586 3587 3588 3589
  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);
  }
}