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

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


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

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

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

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

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

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

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

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

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

#include "PHY/types.h"
66

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

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

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

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

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

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

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

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

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

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

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

#define FRAME_PERIOD    100000000ULL
#define DAQ_PERIOD      66667ULL

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

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

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


Raymond Knopp's avatar
 
Raymond Knopp committed
147

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

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

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

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

#ifdef RTAI
171

172 173
static long                      main_eNB_thread;
static long                      main_ue_thread;
174

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

179
pthread_attr_t                  attr_dlsch_threads;
180 181
pthread_attr_t                  attr_UE_thread;

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

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

191

192 193


194
struct sched_param              sched_param_UE_thread;
195

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
212

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

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

223

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
234

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

238
static char                     threequarter_fs=0;
239

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

243
openair0_rf_map rf_map[MAX_NUM_CCs];
244

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

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

254 255
FILE *input_fd=NULL;

256

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

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

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

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

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

#endif
300 301

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
317
int multi_thread=1;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
318
uint32_t target_dl_mcs = 28; //maximum allowed mcs
319
uint32_t target_ul_mcs = 10;
320
uint32_t timing_advance = 0;
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
#if !defined(ENABLE_ITTI)
384 385 386 387 388 389 390 391
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);
392

393 394 395 396
    // print out all the frames to stderr
    fprintf(stderr, "Error: signal %d:\n", sig);
    backtrace_symbols_fd(array, size, 2);
    exit(-1);
397 398
  } else {
    printf("trying to exit gracefully...\n");
399
    oai_exit = 1;
400 401
  }
}
402
#endif
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
#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
418 419
  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");
420
  printf("  --no-L2-connect bypass L2 and upper layers\n");
421 422 423 424
  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");
425
  printf("  -C Set the downlink frequency for all component carriers\n");
426 427 428 429 430 431 432 433 434 435
  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
436
  printf("  -r Set the PRB, valid values: 6, 25, 50, 100  \n");    
437 438
  printf("  -S Skip the missed slots/subframes \n");    
  printf("  -t Set the maximum uplink MCS\n");
439
  printf("  -T Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n");
440 441 442 443
  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);    
444

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

  oai_exit = 1;

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

  //rt_sleep_ns(FRAME_PERIOD);

  //exit (-1);
}

464

465
#ifdef XFORMS
466

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

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

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

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

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

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

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

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

513
# ifdef ENABLE_XFORMS_WRITE_STATS
514 515

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

520
#endif
521

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
534
    } else {
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
535 536
#ifdef OPENAIR2
      len = dump_eNB_l2_stats (stats_buffer, 0);
knopp's avatar
knopp committed
537 538 539
      //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
540 541
#endif
      len = dump_eNB_stats (PHY_vars_eNB_g[0][0], stats_buffer, 0);
542

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

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

550
      for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
551 552 553 554 555
	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
556
      }
557

558
    }
559

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

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

567
# ifdef ENABLE_XFORMS_WRITE_STATS
568

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

583
# endif
584

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

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

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

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

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

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

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

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

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

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

632 633 634

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

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

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

  pthread_exit((void*) arg);

}

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

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

676 677 678
  time_t timer;
  struct tm *now;

679
  struct sched_param sched_param;
680 681

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

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

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

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

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


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

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

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


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

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

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

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

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

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

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

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

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

}
#endif

787 788


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

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

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

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

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
819

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

829 830 831
      itti_receive_msg (TASK_L2L1, &message_p);

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

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

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

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
889

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

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

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
908

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

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

     if ((((phy_vars_eNB->lte_frame_parms.tdd_config==0) ||
	  (phy_vars_eNB->lte_frame_parms.tdd_config==1) ||
	  (phy_vars_eNB->lte_frame_parms.tdd_config==2) ||
	  (phy_vars_eNB->lte_frame_parms.tdd_config==6)) && 
	  (subframe==0)) || (subframe==5)) {
       // turn on tx switch N_TA_offset before
       //LOG_D(HW,"subframe %d, time to switch to tx (N_TA_offset %d, slot_offset %d) \n",subframe,phy_vars_eNB->N_TA_offset,slot_offset);
       for (i=0; i<phy_vars_eNB->N_TA_offset; i++) {
	 tx_offset = (int)slot_offset+time_offset[aa]+i-phy_vars_eNB->N_TA_offset/2;
	 if (tx_offset<0)
	   tx_offset += LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti;
	 
	 if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti))
	   tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti;
	 
	 phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset] = 0x00000000;
       }
     }
Raymond Knopp's avatar
 
Raymond Knopp committed
993 994 995 996
    }
  }
}

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

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

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

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

1028 1029
  MSC_START_USE();

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1047
#else
1048
#ifdef LOWLATENCY
1049 1050
  struct sched_attr attr;
  unsigned int flags = 0;
navid's avatar
navid committed
1051 1052 1053 1054 1055 1056 1057
  uint64_t runtime  = (uint64_t) (get_runtime_tx(proc->subframe, runtime_phy_tx, target_dl_mcs,frame_parms[0]->N_RB_DL,cpuf,PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx) *  1000000); 
  uint64_t deadline = 1   *  1000000; // each tx thread will finish within 1ms
  uint64_t period   = 1   * 10000000; // each tx thread has a period of 10ms from the starting point
  if (runtime > 1000000 ){
    LOG_W(HW,"estimated runtime %d is larger than 1ms, adjusting\n",runtime);
    runtime = (0.97 * 100) * 10000; 
  }
1058

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

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

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

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

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

  mlockall(MCL_CURRENT | MCL_FUTURE);

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

1087
  while (!oai_exit) {
1088

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

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

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

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

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

    if (oai_exit) break;
1114

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

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

1138 1139 1140
      if (oai_exit)
        break;

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

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

1159
    do_OFDM_mod_rt( proc->subframe_tx, PHY_vars_eNB_g[0][proc->CC_id] );
kaltenbe's avatar
kaltenbe committed
1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173
    /*
    short *txdata = (short*)&PHY_vars_eNB_g[0][proc->CC_id]->lte_eNB_common_vars.txdata[0][0][proc->subframe_tx*PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.samples_per_tti];
    int i;
    for (i=0;i<7680*2;i+=8) {
      txdata[i] = 2047;
      txdata[i+1] = 0;
      txdata[i+2] = 0;
      txdata[i+3] = 2047;
      txdata[i+4] = -2047;
      txdata[i+5] = 0;
      txdata[i+6] = 0;
      txdata[i+7] = -2047;
    }
    */
1174 1175 1176 1177 1178
    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
1179

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

1190 1191
    if (proc->frame_tx==1024)
      proc->frame_tx=0;
1192
    stop_meas( &softmodem_stats_tx_sf[proc->subframe] );
1193 1194 1195 1196 1197 1198 1199
#ifdef LOWLATENCY
    if (opp_enabled){
      if(softmodem_stats_tx_sf[proc->subframe].diff_now/(cpuf) > attr.sched_runtime){
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_TX_ENB, (softmodem_stats_tx_sf[proc->subframe].diff_now/cpuf - attr.sched_runtime)/1000000.0);
      }
    }
#endif 
1200 1201
    print_meas_now(&softmodem_stats_tx_sf[proc->subframe],"eNB_TX_SF",proc->subframe, tx_time_file);

1202 1203
  }

1204 1205


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
  struct sched_attr attr;
  unsigned int flags = 0;
navid's avatar
navid committed
1271 1272 1273 1274 1275 1276 1277 1278
  uint64_t runtime  = get_runtime_rx(proc->subframe, runtime_phy_rx, target_ul_mcs,frame_parms[0]->N_RB_DL,cpuf,PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx)  *  1000000; 
  uint64_t deadline = 1   *  1000000;
  uint64_t period   = 1   * 10000000; // each rx thread has a period of 10ms from the starting point
  if (runtime  > 2300000 ) {
    LOG_W(HW,"estimated rx runtime %d is larger than expected, adjusting\n",runtime);
    runtime   = 2300000;
    deadline  = runtime + 100000;
  }
1279

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

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

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

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

  mlockall(MCL_CURRENT | MCL_FUTURE);

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

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

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

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

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

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

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

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

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

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

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

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

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

    proc->frame_rx++;
1360

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

1364
    stop_meas( &softmodem_stats_rx_sf[proc->subframe] );
1365 1366 1367 1368 1369 1370 1371
#ifdef LOWLATENCY
    if (opp_enabled){
      if(softmodem_stats_rx_sf[proc->subframe].diff_now/(cpuf) > attr.sched_runtime){
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_RX_ENB, (softmodem_stats_rx_sf[proc->subframe].diff_now/cpuf - attr.sched_runtime)/1000000.0);
      }
    }
#endif  
1372
    print_meas_now(&softmodem_stats_rx_sf[proc->subframe],"eNB_RX_SF",proc->subframe, rx_time_file);
Raymond Knopp's avatar
 
Raymond Knopp committed
1373
  }
1374

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

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

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

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



Raymond Knopp's avatar
 
Raymond Knopp committed
1396

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

1402 1403 1404
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    for (i=0; i<NUM_ENB_THREADS; i++) {
      // set the stack size
navid's avatar
navid committed
1405
     
1406

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


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

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

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

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

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

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

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

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

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

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

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

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

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

1534 1535
#ifdef DEBUG_THREADS

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

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

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


Raymond Knopp's avatar
 
Raymond Knopp committed
1558 1559


1560

Raymond Knopp's avatar
 
Raymond Knopp committed
1561

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

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

  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
1592

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

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

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

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

Lionel Gauthier's avatar
Lionel Gauthier committed
1619

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

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

1633
#endif
1634 1635
#endif

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

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

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

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

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

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

1666
  pthread_mutex_unlock(&sync_mutex);
1667

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

1670
  int frame = 0;
1671

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

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

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

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

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

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

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

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

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

    
1747
    }
1748

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

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

    delay_cnt = 0;
1757

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

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

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

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

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

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

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

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

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

1805
      clock_gettime( CLOCK_MONOTONIC, &trx_time0 );
1806

1807
       start_meas( &softmodem_stats_hw );
1808

1809
      openair0_timestamp timestamp;
1810 1811
      int i=0;
      // prepare rx buffer pointers
1812
      for (i=0; i<PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx; i++)
1813 1814 1815 1816 1817 1818 1819
        rxp[i] = (void*)&rxdata[i][rx_pos];
	// check if nsymb_read == spp
	// map antenna port i to the cc_id. Now use the 1:1 mapping
	rxs = openair0.trx_read_func(&openair0,
				     &timestamp,
				     rxp,
				     spp,
1820 1821
				     PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx);
      
1822 1823
      stop_meas( &softmodem_stats_hw );
      clock_gettime( CLOCK_MONOTONIC, &trx_time1 );
Raymond Knopp's avatar
 
Raymond Knopp committed
1824

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

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


1834 1835 1836 1837 1838 1839
    
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
      // prepare tx buffer pointers
      for (i=0; i<PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx; i++)
	txp[i] = (void*)&txdata[i][tx_pos];
      // if symb_written < spp ==> error 
navid's avatar
navid committed
1840
      if (frame > 50) {
1841
	openair0.trx_write_func(&openair0,
1842
				(timestamp+(openair0_cfg[card].tx_scheduling_advance)-openair0_cfg[card].tx_sample_advance),
1843 1844 1845 1846
				txp,
				spp,
				PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx,
				1);
navid's avatar
navid committed
1847 1848
      }
      
1849
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, timestamp&0xffffffff );
1850
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp+(openair0_cfg[card].tx_scheduling_advance)-openair0_cfg[card].tx_sample_advance)&0xffffffff );
1851 1852 1853 1854

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

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

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

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1902 1903

#endif // USRP
1904

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

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

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

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

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

    timing_info.n_samples++;

    if ((slot&1) == 1) {
1925
      // odd slot
1926
#ifdef EXMIMO
1927
      int sf = ((slot>>1)+1)%10;
Raymond Knopp's avatar
 
Raymond Knopp committed
1928
#else
1929
      int sf = hw_subframe;
Raymond Knopp's avatar
 
Raymond Knopp committed
1930
#endif
1931 1932
      if (frame>50) {
	for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1933
#ifdef EXMIMO
1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948
	  
	  if (pthread_mutex_lock(&PHY_vars_eNB_g[0][CC_id]->proc[sf].mutex_tx) != 0) {
	    LOG_E(PHY,"[eNB] ERROR pthread_mutex_lock for eNB TX thread %d (IC %d)\n",sf,PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_tx);
	  } else {
	    //          LOG_I(PHY,"[eNB] Waking up eNB process %d (IC %d)\n",sf,PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt);
	    PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_tx++;
	    pthread_mutex_unlock(&PHY_vars_eNB_g[0][CC_id]->proc[sf].mutex_tx);
	    
	    if (PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_tx == 0) {
	      if (pthread_cond_signal(&PHY_vars_eNB_g[0][CC_id]->proc[sf].cond_tx) != 0) {
		LOG_E(PHY,"[eNB] ERROR pthread_cond_signal for eNB TX thread %d\n",sf);
		exit_fun("nothing to add");
	      }
	    } else {
	      LOG_W(PHY,"[eNB] Frame %d, eNB TX thread %d busy!!\n",PHY_vars_eNB_g[0][CC_id]->proc[sf].frame_tx,sf);
1949
	      exit_fun("nothing to add");
1950 1951 1952
	    }
	  }
	  
Raymond Knopp's avatar
 
Raymond Knopp committed
1953 1954
#endif

1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977
	  if (pthread_mutex_lock(&PHY_vars_eNB_g[0][CC_id]->proc[sf].mutex_rx) != 0) {
	    LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB RX thread %d (IC %d)\n", sf, PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_rx );
	    exit_fun( "error locking mutex_rx" );
	    break;
	  }
	  
	  int cnt_rx = ++PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_rx;
	  
	  pthread_mutex_unlock( &PHY_vars_eNB_g[0][CC_id]->proc[sf].mutex_rx );
	  
	  if (cnt_rx == 0) {
	    // the thread was presumably waiting where it should and can now be woken up
	    if (pthread_cond_signal(&PHY_vars_eNB_g[0][CC_id]->proc[sf].cond_rx) != 0) {
	      LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB RX thread %d\n", sf );
	      exit_fun( "ERROR pthread_cond_signal" );
	      break;
	    }
	  } else {
	    LOG_W( PHY, "[eNB] Frame %d, eNB RX thread %d busy!! instance_cnt %d CC_id %d\n", PHY_vars_eNB_g[0][CC_id]->proc[sf].frame_rx, sf, PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_rx, CC_id );
	    exit_fun( "RX thread busy" );
	    break;
	  }
	}
Raymond Knopp's avatar
 
Raymond Knopp committed
1978
      }
1979 1980 1981 1982
    }

#ifdef EXMIMO
    slot++;
1983

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

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

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

#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2001

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

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

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

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

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

2028

Raymond Knopp's avatar
 
Raymond Knopp committed
2029

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2030

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



2049 2050

  const Enb_properties_array_t *enb_properties;
2051

2052 2053 2054 2055 2056 2057 2058
  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,
2059
    LONG_OPTION_NO_L2_CONNECT,
Raymond Knopp's avatar
 
Raymond Knopp committed
2060
    LONG_OPTION_CALIB_PRACH_TX,
2061 2062
    LONG_OPTION_RXGAIN,
    LONG_OPTION_TXGAIN,
2063
    LONG_OPTION_SCANCARRIER,
2064 2065 2066
    LONG_OPTION_MAXPOWER,
    LONG_OPTION_DUMP_FRAME,
    LONG_OPTION_LOOPMEMORY
2067
  };
2068

2069 2070 2071 2072 2073 2074 2075
  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
2076 2077 2078 2079
    {"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},
2080
    {"ue-max-power",   required_argument,  NULL, LONG_OPTION_MAXPOWER},
2081 2082
    {"ue-dump-frame", no_argument, NULL, LONG_OPTION_DUMP_FRAME},
    {"loop-memory", required_argument, NULL, LONG_OPTION_LOOPMEMORY},
2083 2084 2085
    {NULL, 0, NULL, 0}
  };

2086
  while ((c = getopt_long (argc, argv, "A:a:C:dEK:g:F:G:hqO:m:SUVRM:r:P:Ws:t:Tx:",long_options,NULL)) != -1) {
2087
    switch (c) {
2088 2089 2090 2091 2092
    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];

2093 2094 2095 2096
    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;
2097

2098 2099 2100 2101 2102
    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;
2103

2104 2105 2106 2107
    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
2108
      break;
2109

2110 2111 2112 2113 2114
    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;
2115

2116 2117 2118
    case LONG_OPTION_DEBUG_UE_PRACH:
      mode = debug_prach;
      break;
2119

2120 2121 2122
    case LONG_OPTION_NO_L2_CONNECT:
      mode = no_L2_connect;
      break;
2123

Raymond Knopp's avatar
 
Raymond Knopp committed
2124 2125 2126 2127
    case LONG_OPTION_CALIB_PRACH_TX:
      mode = calib_prach_tx;
      break;

2128
    case LONG_OPTION_RXGAIN:
2129 2130
      for (i=0; i<4; i++)
        rx_gain[0][i] = atof(optarg);
2131

2132
      break;
2133

2134 2135 2136
    case LONG_OPTION_TXGAIN:
      for (i=0; i<4; i++)
        tx_gain[0][i] = atof(optarg);
2137

2138
      break;
2139

2140 2141 2142 2143 2144
    case LONG_OPTION_SCANCARRIER:
      UE_scan_carrier=1;

      break;

2145 2146 2147 2148 2149 2150 2151 2152 2153 2154
    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;

2155 2156 2157
    case 'M':
#ifdef ETHERNET
      strcpy(rrh_eNB_ip,optarg);
2158
#endif
2159
      break;
2160

2161 2162 2163 2164
    case 'A':
      timing_advance = atoi (optarg);
      break;

2165
    case 'C':
2166 2167 2168 2169 2170 2171
      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]);
2172
      }
2173

2174
      UE_scan=0;
2175

2176
      break;
2177

Florian Kaltenberger's avatar
Florian Kaltenberger committed
2178 2179 2180 2181
    case 'a':
      chain_offset = atoi(optarg);
      break;

2182 2183 2184 2185
    case 'd':
#ifdef XFORMS
      do_forms=1;
      printf("Running with XFORMS!\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2186
#endif
2187
      break;
2188 2189 2190 2191
      
    case 'E':
      threequarter_fs=1;
      break;
2192

2193 2194 2195
    case 'K':
#if defined(ENABLE_ITTI)
      itti_dump_file = strdup(optarg);
2196
#else
2197
      printf("-K option is disabled when ENABLE_ITTI is not defined\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2198
#endif
2199
      break;
2200

2201 2202 2203
    case 'O':
      conf_config_file_name = optarg;
      break;
2204

2205 2206 2207
    case 'U':
      UE_flag = 1;
      break;
2208

2209 2210 2211
    case 'm':
      target_dl_mcs = atoi (optarg);
      break;
2212

2213 2214 2215
    case 't':
      target_ul_mcs = atoi (optarg);
      break;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2216
#ifdef OPENAIR2
2217

2218 2219 2220 2221 2222 2223 2224
    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");
      /*
2225 2226 2227
      if (optarg == NULL){
      in_ip[0] =NULL;
      printf("Enabling OPT for wireshark for local interface");
2228
      } else {
2229 2230 2231
      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);
2232 2233 2234
      }
      */
      break;
2235

2236
    case 'P':
2237 2238
      opt_type = OPT_PCAP;
      opt_enabled=1;
2239 2240 2241 2242 2243

      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");
2244
      } else {
2245 2246 2247
        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);
2248
      }
2249 2250

      break;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2251
#endif
2252

Raymond Knopp's avatar
 
Raymond Knopp committed
2253 2254 2255
    case 'V':
      ouput_vcd = 1;
      break;
2256

Raymond Knopp's avatar
 
Raymond Knopp committed
2257
    case  'q':
Raymond Knopp's avatar
 
Raymond Knopp committed
2258 2259
      opp_enabled = 1;
      break;
2260

Raymond Knopp's avatar
 
Raymond Knopp committed
2261 2262 2263
    case  'R' :
      online_log_messages =1;
      break;
2264

Raymond Knopp's avatar
 
Raymond Knopp committed
2265
    case 'r':
2266
      UE_scan = 0;
2267

2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293
      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
2294
      }
2295

2296
      break;
2297

Raymond Knopp's avatar
 
Raymond Knopp committed
2298
    case 's':
2299
#if defined(OAI_USRP) || defined(CPRIGW)
Raymond Knopp's avatar
 
Raymond Knopp committed
2300 2301

      clock_src = atoi(optarg);
2302

Raymond Knopp's avatar
 
Raymond Knopp committed
2303
      if (clock_src == 0) {
2304 2305 2306 2307 2308
        //  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
2309
      }
2310

Raymond Knopp's avatar
 
Raymond Knopp committed
2311 2312 2313 2314
#else
      printf("Note: -s not defined for ExpressMIMO2\n");
#endif
      break;
2315

2316 2317 2318 2319
    case 'S':
      exit_missed_slots=0;
      printf("Skip exit for missed slots\n");
      break;
2320

2321
    case 'g':
Raymond Knopp's avatar
 
Raymond Knopp committed
2322
      glog_level=atoi(optarg); // value between 1 - 9
2323
      break;
2324 2325

    case 'F':
2326
#ifdef EXMIMO
2327 2328
      sprintf(rxg_fname,"%srxg.lime",optarg);
      rxg_fd = fopen(rxg_fname,"r");
2329

2330
      if (rxg_fd) {
2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348
        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);

2349
#endif
2350
      break;
2351

2352 2353 2354
    case 'G':
      glog_verbosity=atoi(optarg);// value from 0, 0x5, 0x15, 0x35, 0x75
      break;
2355

2356 2357
    case 'x':
      transmission_mode = atoi(optarg);
2358

2359
      if (transmission_mode > 2) {
2360 2361
        printf("Transmission mode > 2 (%d) not supported for the moment\n",transmission_mode);
        exit(-1);
2362
      }
2363
      break;
2364

2365 2366 2367
    case 'T':
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) 
	frame_parms[CC_id]->frame_type = TDD;
2368
      break;
2369

2370 2371 2372 2373
    case 'h':
      help ();
      exit (-1);
       
Raymond Knopp's avatar
 
Raymond Knopp committed
2374
    default:
2375 2376
      help ();
      exit (-1);
Raymond Knopp's avatar
 
Raymond Knopp committed
2377
      break;
2378 2379
    }
  }
2380

Raymond Knopp's avatar
 
Raymond Knopp committed
2381 2382
  if (UE_flag == 0)
    AssertFatal(conf_config_file_name != NULL,"Please provide a configuration file\n");
2383 2384


Raymond Knopp's avatar
 
Raymond Knopp committed
2385
  if ((UE_flag == 0) && (conf_config_file_name != NULL)) {
2386
    int i,j;
2387

Raymond Knopp's avatar
 
Raymond Knopp committed
2388
    NB_eNB_INST = 1;
2389

Raymond Knopp's avatar
 
Raymond Knopp committed
2390 2391
    /* Read eNB configuration file */
    enb_properties = enb_config_init(conf_config_file_name);
2392

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

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

2419

2420
#ifdef OPENAIR2
2421

2422 2423 2424
      init_all_otg(0);
      g_otg->seed = 0;
      init_seeds(g_otg->seed);
2425 2426 2427 2428 2429 2430 2431 2432 2433 2434

      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");
2435
      }
2436

2437
      init_predef_traffic(enb_properties->properties[i]->num_otg_elements, 1);
2438

2439
#endif
2440

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

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

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

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

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

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

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

2521 2522 2523
  PHY_VARS_UE *UE[MAX_NUM_CCs];

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

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

2529
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2530 2531
    frame_parms[CC_id] = (LTE_DL_FRAME_PARMS*) malloc(sizeof(LTE_DL_FRAME_PARMS));
    /* Set some default values that may be overwritten while reading options */
2532
    frame_parms[CC_id]->frame_type          = FDD;
Raymond Knopp's avatar
 
Raymond Knopp committed
2533 2534
    frame_parms[CC_id]->tdd_config          = 3;
    frame_parms[CC_id]->tdd_config_S        = 0;
2535 2536
    frame_parms[CC_id]->N_RB_DL             = 100;
    frame_parms[CC_id]->N_RB_UL             = 100;
Raymond Knopp's avatar
 
Raymond Knopp committed
2537
    frame_parms[CC_id]->Ncp                 = NORMAL;
Raymond Knopp's avatar
 
Raymond Knopp committed
2538 2539
    frame_parms[CC_id]->Ncp_UL              = NORMAL;
    frame_parms[CC_id]->Nid_cell            = Nid_cell;
Raymond Knopp's avatar
 
Raymond Knopp committed
2540
    frame_parms[CC_id]->num_MBSFN_config    = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2541 2542 2543
    frame_parms[CC_id]->nb_antennas_tx_eNB  = 1;
    frame_parms[CC_id]->nb_antennas_tx      = 1;
    frame_parms[CC_id]->nb_antennas_rx      = 1;
Raymond Knopp's avatar
 
Raymond Knopp committed
2544
  }
2545

2546 2547 2548 2549 2550
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    downlink_frequency[CC_id][0] = 2680000000; // Use float to avoid issue with frequency over 2^31.
    downlink_frequency[CC_id][1] = downlink_frequency[CC_id][0];
    downlink_frequency[CC_id][2] = downlink_frequency[CC_id][0];
    downlink_frequency[CC_id][3] = downlink_frequency[CC_id][0];
2551
    //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
2552
  }
2553 2554
  logInit();
 
2555
  get_options (argc, argv); //Command-line options
2556 2557 2558
 
  
  // initialize the log (see log.h for details)
Florian Kaltenberger's avatar
Florian Kaltenberger committed
2559 2560
  set_glog(glog_level, glog_verbosity);

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

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

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

2583
    set_comp_log(HW,      hw_log_level, hw_log_verbosity, 1);
2584
#ifdef OPENAIR2
2585 2586 2587 2588 2589
    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);

2590
#else
2591
    set_comp_log(PHY,     LOG_INFO,   LOG_HIGH, 1);
2592
#endif
2593 2594 2595 2596
    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);
2597
#if defined(ENABLE_ITTI)
2598
    set_comp_log(EMU,     LOG_INFO,   LOG_MED, 1);
2599
# if defined(ENABLE_USE_MME)
2600 2601 2602 2603
    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);
2604
# endif
2605
#if defined(ENABLE_SECURITY)
2606
    set_comp_log(OSA,    osa_log_level,   osa_log_verbosity, 1);
2607
#endif
2608
#endif
2609
#ifdef LOCALIZATION
2610 2611 2612 2613 2614 2615 2616 2617 2618
    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
2619
    }
2620
  }
2621

Raymond Knopp's avatar
 
Raymond Knopp committed
2622 2623
  if (ouput_vcd) {
    if (UE_flag==1)
2624
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_UE.vcd");
Raymond Knopp's avatar
 
Raymond Knopp committed
2625
    else
2626
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_eNB.vcd");
Raymond Knopp's avatar
 
Raymond Knopp committed
2627
  }
2628

2629
  if (opp_enabled ==1){
2630
    reset_opp_meas();
2631 2632
  }
  cpuf=get_cpu_freq_GHz();
2633

2634
#if defined(ENABLE_ITTI)
2635

Raymond Knopp's avatar
 
Raymond Knopp committed
2636 2637
  if (UE_flag == 1) {
    log_set_instance_type (LOG_INSTANCE_UE);
2638
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
2639 2640
    log_set_instance_type (LOG_INSTANCE_ENB);
  }
2641

Raymond Knopp's avatar
 
Raymond Knopp committed
2642
  itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, itti_dump_file);
2643
 
2644 2645
  // initialize mscgen log after ITTI
  MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX);
2646 2647
#endif
 
2648
#ifdef OPENAIR2
2649

2650 2651
  if (opt_type != OPT_NONE) {
    radio_type_t radio_type;
2652

2653 2654
    if (frame_parms[0]->frame_type == FDD)
      radio_type = RADIO_TYPE_FDD;
2655
    else
2656
      radio_type = RADIO_TYPE_TDD;
2657

2658 2659 2660
    if (init_opt(in_path, in_ip, NULL, radio_type) == -1)
      LOG_E(OPT,"failed to run OPT \n");
  }
2661

2662
#endif
2663
#ifdef PDCP_USE_NETLINK
Raymond Knopp's avatar
 
Raymond Knopp committed
2664
  netlink_init();
2665 2666 2667
#if defined(PDCP_USE_NETLINK_QUEUES)
  pdcp_netlink_init();
#endif
2668 2669
#endif

2670
#if !defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
2671 2672 2673
  // to make a graceful exit when ctrl-c is pressed
  signal(SIGSEGV, signal_handler);
  signal(SIGINT, signal_handler);
2674
#endif
2675 2676

#ifndef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
2677 2678 2679 2680
  check_clock();
#endif

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

2684 2685 2686 2687 2688 2689 2690 2691 2692
    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
2693 2694 2695 2696 2697 2698 2699 2700
    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;
2701
    frame_parms[CC_id]->threequarter_fs = threequarter_fs;
2702 2703
    init_ul_hopping(frame_parms[CC_id]);
    init_frame_parms(frame_parms[CC_id],1);
2704 2705
    //   phy_init_top(frame_parms[CC_id]);
    phy_init_lte_top(frame_parms[CC_id]);
Raymond Knopp's avatar
 
Raymond Knopp committed
2706 2707 2708
  }


2709
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2710
    //init prach for openair1 test
2711
    frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22;
Raymond Knopp's avatar
 
Raymond Knopp committed
2712
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1;
2713
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2714 2715 2716
    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
2717
    // N_ZC = (prach_fmt <4)?839:139;
Raymond Knopp's avatar
 
Raymond Knopp committed
2718
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
2719 2720

  if (UE_flag==1) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2721 2722 2723
    NB_UE_INST=1;
    NB_INST=1;

Raymond Knopp's avatar
 
Raymond Knopp committed
2724 2725
    PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE**));
    PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_UE*)*MAX_NUM_CCs);
2726 2727

    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
2728 2729 2730 2731

      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
2732
#ifndef OPENAIR2
2733 2734 2735 2736 2737 2738 2739 2740 2741

      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
2742
      }
2743

2744
#endif
2745 2746 2747


      UE[CC_id]->UE_scan = UE_scan;
2748
      UE[CC_id]->UE_scan_carrier = UE_scan_carrier;
2749 2750 2751
      UE[CC_id]->mode    = mode;

      compute_prach_seq(&UE[CC_id]->lte_frame_parms.prach_config_common,
2752 2753 2754
                        UE[CC_id]->lte_frame_parms.frame_type,
                        UE[CC_id]->X_u);

2755
      UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1234;
2756
#ifndef OPENAIR2
2757
      UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1235;
2758
#endif
2759

2760
#ifdef EXMIMO
2761

2762 2763 2764 2765
      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
2766
      }
2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785

      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
2786
      }
2787

2788
#else
2789
      UE[CC_id]->rx_total_gain_dB =  (int)rx_gain[CC_id][0];
2790
#endif
2791

2792
      UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id];
2793

2794 2795


2796
#ifdef EXMIMO
2797

Raymond Knopp's avatar
 
Raymond Knopp committed
2798
      //N_TA_offset
2799
      if (UE[CC_id]->lte_frame_parms.frame_type == TDD) {
2800 2801 2802 2803 2804 2805 2806 2807
        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
2808
      }
2809

2810
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
2811
      //already taken care of in lte-softmodem
2812
      UE[CC_id]->N_TA_offset = 0;
2813
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2814
    }
2815

Raymond Knopp's avatar
 
Raymond Knopp committed
2816 2817 2818 2819
    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;
2820 2821 2822



Raymond Knopp's avatar
 
Raymond Knopp committed
2823
    //  printf("tx_max_power = %d -> amp %d\n",tx_max_power,get_tx_amp(tx_max_power,tx_max_power));
2824 2825 2826 2827 2828 2829
  } 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++) {
2830
      PHY_vars_eNB_g[0][CC_id] = init_lte_eNB(frame_parms[CC_id],0,frame_parms[CC_id]->Nid_cell,cooperation_flag,transmission_mode,abstraction_flag);
2831 2832
      PHY_vars_eNB_g[0][CC_id]->CC_id = CC_id;

2833
#ifndef OPENAIR2
2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849

      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
2850

2851
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
2852

2853
      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
2854

2855
#else
2856 2857 2858
      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
2859

2860 2861 2862
      // 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
2863

2864
#endif
2865

2866
#ifdef EXMIMO
2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877

      //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
2878
      }
2879

2880
#else
2881
      //already taken care of in lte-softmodem.c
2882 2883
      PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 0;
#endif
2884

2885
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
2886 2887


2888 2889 2890 2891 2892 2893 2894 2895 2896
    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;

  }
2897 2898 2899 2900
#ifndef RTAI
  fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx);
  cpuf=get_cpu_freq_GHz();
#endif 
2901

Raymond Knopp's avatar
 
Raymond Knopp committed
2902
  dump_frame_parms(frame_parms[0]);
2903

2904 2905 2906
  for (card=0; card<MAX_CARDS; card++) {

    if(frame_parms[0]->N_RB_DL == 100) {
2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918
      if (frame_parms[0]->threequarter_fs) {
	openair0_cfg[card].sample_rate=23.04e6;
	openair0_cfg[card].samples_per_frame = 230400; 
	openair0_cfg[card].tx_bw = 10e6;
	openair0_cfg[card].rx_bw = 10e6;
      }
      else {
	openair0_cfg[card].sample_rate=30.72e6;
	openair0_cfg[card].samples_per_frame = 307200; 
	openair0_cfg[card].tx_bw = 10e6;
	openair0_cfg[card].rx_bw = 10e6;
      }
2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934
    } else if(frame_parms[0]->N_RB_DL == 50) {
      openair0_cfg[card].sample_rate=15.36e6;
      openair0_cfg[card].samples_per_frame = 153600;
      openair0_cfg[card].tx_bw = 5e6;
      openair0_cfg[card].rx_bw = 5e6;
    } else if (frame_parms[0]->N_RB_DL == 25) {
      openair0_cfg[card].sample_rate=7.68e6;
      openair0_cfg[card].samples_per_frame = 76800;
      openair0_cfg[card].tx_bw = 2.5e6;
      openair0_cfg[card].rx_bw = 2.5e6;
    } else if (frame_parms[0]->N_RB_DL == 6) {
      openair0_cfg[card].sample_rate=1.92e6;
      openair0_cfg[card].samples_per_frame = 19200;
      openair0_cfg[card].tx_bw = 1.5e6;
      openair0_cfg[card].rx_bw = 1.5e6;
    }
2935 2936 2937 2938 2939 2940

    if (frame_parms[0]->frame_type==TDD)
      openair0_cfg[card].duplex_mode = duplex_mode_TDD;
    else //FDD
      openair0_cfg[card].duplex_mode = duplex_mode_FDD;

Raymond Knopp's avatar
 
Raymond Knopp committed
2941
#ifdef ETHERNET
2942

2943
    //calib needed
2944 2945
    openair0_cfg[card].tx_scheduling_advance = 0;
    openair0_cfg[card].tx_sample_advance = 0;
2946 2947 2948 2949 2950
    
    if (frame_parms[0]->N_RB_DL == 6) 
      openair0_cfg[card].samples_per_packet = 256;
    else 
      openair0_cfg[card].samples_per_packet = 1024;
Raymond Knopp's avatar
 
Raymond Knopp committed
2951

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

2955

2956
    printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card,
2957 2958
           ((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
2959 2960
    openair0_cfg[card].Mod_id = 0;
#ifdef ETHERNET
2961 2962

    if (UE_flag) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2963
      printf("ETHERNET: Configuring UE ETH for %s:%d\n",rrh_UE_ip,rrh_UE_port);
2964 2965
      openair0_cfg[card].remote_ip   = &rrh_UE_ip[0];
      openair0_cfg[card].remote_port = rrh_UE_port;
2966 2967
    } else {
      printf("ETHERNET: Configuring eNB ETH for %s:%d\n",rrh_eNB_ip,rrh_eNB_port);
2968 2969
      openair0_cfg[card].remote_ip   = &rrh_eNB_ip[0];
      openair0_cfg[card].remote_port = rrh_eNB_port;
ghaddab's avatar
ghaddab committed
2970
    }
2971
    openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL;
Raymond Knopp's avatar
 
Raymond Knopp committed
2972
#endif
2973

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

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

2983 2984 2985 2986 2987 2988 2989 2990
      openair0_cfg[card].tx_freq[i] = (UE_flag==0) ? downlink_frequency[0][i] : downlink_frequency[0][i]+uplink_frequency_offset[0][i];
      openair0_cfg[card].rx_freq[i] = (UE_flag==0) ? downlink_frequency[0][i] + uplink_frequency_offset[0][i] : downlink_frequency[0][i];
      printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n",
             card,i, openair0_cfg[card].tx_gain[i],
             openair0_cfg[card].rx_gain[i],
             openair0_cfg[card].tx_freq[i],
             openair0_cfg[card].rx_freq[i]);
      
2991
      openair0_cfg[card].autocal[i] = 1;
2992
      openair0_cfg[card].tx_gain[i] = tx_gain[0][i];
2993 2994 2995 2996
      if (UE_flag == 0) {
	openair0_cfg[card].rx_gain[i] = PHY_vars_eNB_g[0][0]->rx_total_gain_eNB_dB;
      }
      else {
2997
	openair0_cfg[card].rx_gain[i] = PHY_vars_UE_g[0][0]->rx_total_gain_dB;
2998
      }
2999

3000
#if 0  // UHD 3.8     
3001 3002
      switch(frame_parms[0]->N_RB_DL) {
      case 6:
3003
        openair0_cfg[card].rx_gain[i] -= 12;
3004 3005
        break;

3006
      case 25:
3007
        openair0_cfg[card].rx_gain[i] -= 6;
3008 3009
        break;

3010
      case 50:
3011 3012 3013 3014 3015
        openair0_cfg[card].rx_gain[i] -= 3;
        break;

      case 100:
        openair0_cfg[card].rx_gain[i] -= 0;
3016 3017
        break;

3018
      default:
3019
        break;
3020
      }
3021
#endif      
3022

Raymond Knopp's avatar
 
Raymond Knopp committed
3023
    }
3024

3025
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3026
  }
3027

navid's avatar
navid committed
3028 3029
  openair0.func_type = BBU_FUNC;
  openair0_cfg[0].log_level = glog_level;
3030

3031 3032 3033 3034 3035 3036 3037 3038
  if (mode!=loop_through_memory){
    int ret;
    ret= openair0_device_init(&openair0, &openair0_cfg[0]);
    printf("openair0_device_init returns %d\n",ret);
    if (ret<0) {
      printf("Exiting, cannot initialize device\n");
      exit(-1);
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3039
  }
3040
  else if (mode==loop_through_memory) {    
3041
  }
3042
 
3043
  printf("Done\n");
3044 3045 3046

  mac_xface = malloc(sizeof(MAC_xface));

3047
#ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
3048
  int eMBMS_active=0;
3049

Raymond Knopp's avatar
 
Raymond Knopp committed
3050
  l2_init(frame_parms[0],eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL,
3051 3052 3053 3054
          0,// cba_group_active
          0); // HO flag


3055 3056
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3057
  mac_xface->macphy_exit = &exit_fun;
3058

winckel's avatar
winckel committed
3059
#if defined(ENABLE_ITTI)
3060

Raymond Knopp's avatar
 
Raymond Knopp committed
3061
  if (create_tasks(UE_flag ? 0 : 1, UE_flag ? 1 : 0) < 0) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3062
    printf("cannot create ITTI tasks\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3063 3064
    exit(-1); // need a softer mode
  }
3065

Raymond Knopp's avatar
 
Raymond Knopp committed
3066
  printf("ITTI tasks created\n");
winckel's avatar
winckel committed
3067
#endif
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3068 3069

#ifdef OPENAIR2
3070
  if (UE_flag==1) {
3071
    printf("Filling UE band info\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3072
    fill_ue_band_info();
3073
    mac_xface->dl_phy_sync_success (0, 0, 0, 1);
3074
  } else
3075
    mac_xface->mrbch_phy_sync_failure (0, 0, 0);
3076

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3077
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3078

3079
  /* #ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
3080 3081 3082 3083 3084 3085
  //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
3086 3087 3088 3089 3090 3091
  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
3092 3093 3094
  }
  init_predef_traffic(UE_flag ? 1 : 0, UE_flag ? 0 : 1);
  //  }
3095
  #endif */
Raymond Knopp's avatar
 
Raymond Knopp committed
3096

3097
#ifdef EXMIMO
3098
  number_of_cards = openair0_num_detected_cards;
3099 3100
#else
  number_of_cards = 1;
3101
#endif
3102

3103

3104

3105
  for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3106
    rf_map[CC_id].card=0;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3107
    rf_map[CC_id].chain=CC_id+chain_offset;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3108
  }
3109

Raymond Knopp's avatar
 
Raymond Knopp committed
3110 3111
  // connect the TX/RX buffers
  if (UE_flag==1) {
3112
#ifdef OAI_USRP
3113
    openair_daq_vars.timing_advance = timing_advance;
3114
#else
3115
    openair_daq_vars.timing_advance = 160;
3116
#endif
3117
    if (setup_ue_buffers(UE,&openair0_cfg[0],rf_map)!=0) {
3118 3119 3120
      printf("Error setting up eNB buffer\n");
      exit(-1);
    }
3121

3122
    printf("Setting UE buffer to all-RX\n");
3123

3124
    // Set LSBs for antenna switch (ExpressMIMO)
3125
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3126
      for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++)
3127 3128
        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
3129
    }
3130

3131 3132 3133 3134 3135 3136 3137
    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
3138
    //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX;
3139
  } else {
3140
    openair_daq_vars.timing_advance = 0;
3141

3142 3143 3144 3145
    if (setup_eNB_buffers(PHY_vars_eNB_g[0],&openair0_cfg[0],rf_map)!=0) {
      printf("Error setting up eNB buffer\n");
      exit(-1);
    }
3146

3147
    printf("Setting eNB buffer to all-RX\n");
3148

3149
    // Set LSBs for antenna switch (ExpressMIMO)
3150
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3151
      for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++)
3152 3153
        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
3154
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3155
  }
3156

3157
#ifdef EXMIMO
3158
  openair0_config(&openair0_cfg[0],UE_flag);
Raymond Knopp's avatar
 
Raymond Knopp committed
3159 3160
#endif

3161
  /*
Raymond Knopp's avatar
 
Raymond Knopp committed
3162 3163
      for (ant=0;ant<4;ant++)
      p_exmimo_config->rf.do_autocal[ant] = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3164
  */
3165 3166

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3169 3170 3171 3172 3173 3174
  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);
3175
  else
Raymond Knopp's avatar
 
Raymond Knopp committed
3176
    printf("[OPENAIR][SCHED][INIT] Problem creating EMOS FIFO %d, error_code %d\n",CHANSOUNDER_FIFO_MINOR,error_code);
3177

3178 3179
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3180
  mlockall(MCL_CURRENT | MCL_FUTURE);
3181 3182

#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3183
  // make main thread LXRT soft realtime
3184
  /* task = */ rt_task_init_schmod(nam2num("MAIN"), 9, 0, 0, SCHED_FIFO, 0xF);
Raymond Knopp's avatar
 
Raymond Knopp committed
3185 3186 3187 3188 3189

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3192 3193
  pthread_cond_init(&sync_cond,NULL);
  pthread_mutex_init(&sync_mutex, NULL);
3194

3195
  /*  this is moved to the eNB main thread */ 
3196

3197
//#if defined(ENABLE_ITTI)
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3198
  // Wait for eNB application initialization to be complete (eNB registration to MME)
3199 3200 3201 3202 3203
  //  if (UE_flag==0) {
  // printf("Waiting for eNB application to be ready\n");
    //wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB);
  // }
  //#endif
3204

Raymond Knopp's avatar
 
Raymond Knopp committed
3205 3206

  // this starts the DMA transfers
3207
#ifdef EXMIMO
3208

Raymond Knopp's avatar
 
Raymond Knopp committed
3209
  if (UE_flag!=1)
3210
    for (card=0; card<openair0_num_detected_cards; card++)
3211
      openair0_start_rt_acquisition(card);
3212

Raymond Knopp's avatar
 
Raymond Knopp committed
3213
#endif
3214 3215

#ifdef XFORMS
3216 3217
  int UE_id;

Raymond Knopp's avatar
 
Raymond Knopp committed
3218 3219
  if (do_forms==1) {
    fl_initialize (&argc, argv, NULL, 0, 0);
3220 3221

    if (UE_flag==0) {
3222
      form_stats_l2 = create_form_stats_form();
3223 3224 3225
      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");
3226 3227

      for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240
	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");
	  }
	}
3241
      }
3242
    } else {
3243 3244 3245 3246 3247 3248 3249
      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
3250
      if (openair_daq_vars.use_ia_receiver) {
3251 3252 3253 3254 3255
        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
3256 3257 3258
      }
    }

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

3261 3262
    if (ret == 0)
      pthread_setname_np( forms_thread, "xforms" );
3263

Raymond Knopp's avatar
 
Raymond Knopp committed
3264 3265
    printf("Scope thread created, ret=%d\n",ret);
  }
3266

3267 3268 3269
#endif

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3270 3271
  ret = pthread_create(&thread3, NULL, emos_thread, NULL);
  printf("EMOS thread created, ret=%d\n",ret);
jiangx's avatar
jiangx committed
3272 3273
  ret = pthread_create(&thread4, NULL, gps_thread, NULL);
  printf("GPS thread created, ret=%d\n",ret);
3274 3275
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3276
  rt_sleep_ns(10*FRAME_PERIOD);
3277 3278

#ifndef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3279
  pthread_attr_init (&attr_dlsch_threads);
3280
  pthread_attr_setstacksize(&attr_dlsch_threads,4*PTHREAD_STACK_MIN);
3281

3282
  pthread_attr_init (&attr_UE_thread);
3283
  pthread_attr_setstacksize(&attr_UE_thread,8192);//5*PTHREAD_STACK_MIN);
3284

3285
#ifndef LOWLATENCY
3286 3287
  sched_param_UE_thread.sched_priority = sched_get_priority_max(SCHED_FIFO);
  pthread_attr_setschedparam(&attr_UE_thread,&sched_param_UE_thread);
3288
  sched_param_dlsch.sched_priority = sched_get_priority_max(SCHED_FIFO); //OPENAIR_THREAD_PRIORITY;
Raymond Knopp's avatar
 
Raymond Knopp committed
3289 3290
  pthread_attr_setschedparam  (&attr_dlsch_threads, &sched_param_dlsch);
  pthread_attr_setschedpolicy (&attr_dlsch_threads, SCHED_FIFO);
3291
  printf("Setting eNB_thread FIFO scheduling policy with priority %d \n", sched_param_dlsch.sched_priority);
3292
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3293

3294 3295
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3296 3297
  // start the main thread
  if (UE_flag == 1) {
3298
    printf("Intializing UE Threads ...\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3299
    init_UE_threads();
3300 3301 3302 3303 3304
#ifdef DLSCH_THREAD
    init_rx_pdsch_thread();
    rt_sleep_ns(FRAME_PERIOD/10);
    init_dlsch_threads();
#endif
3305

3306
    sleep(1);
3307
#ifdef RTAI
3308
    main_ue_thread = rt_thread_create(UE_thread, NULL, 100000000);
3309
#else
3310
    error_code = pthread_create(&main_ue_thread, &attr_UE_thread, UE_thread, NULL);
3311

Raymond Knopp's avatar
 
Raymond Knopp committed
3312 3313 3314
    if (error_code!= 0) {
      LOG_D(HW,"[lte-softmodem.c] Could not allocate UE_thread, error %d\n",error_code);
      return(error_code);
3315
    } else {
3316 3317
      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
3318
    }
3319

3320
#endif
3321
    printf("UE threads created\n");
3322 3323 3324 3325 3326 3327 3328 3329 3330 3331
#ifdef USE_MME

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

#endif



3332
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
3333 3334
    if (multi_thread>0) {
      init_eNB_proc();
3335
      sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3336 3337
      LOG_D(HW,"[lte-softmodem.c] eNB threads created\n");
    }
3338

3339
    printf("Creating main eNB_thread \n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3340
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3341
    main_eNB_thread = rt_thread_create(eNB_thread, NULL, PTHREAD_STACK_MIN);
Raymond Knopp's avatar
 
Raymond Knopp committed
3342
#else
3343
    error_code = pthread_create( &main_eNB_thread, &attr_dlsch_threads, eNB_thread, NULL );
3344

Raymond Knopp's avatar
 
Raymond Knopp committed
3345 3346 3347
    if (error_code!= 0) {
      LOG_D(HW,"[lte-softmodem.c] Could not allocate eNB_thread, error %d\n",error_code);
      return(error_code);
3348
    } else {
3349 3350
      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
3351
    }
3352

Raymond Knopp's avatar
 
Raymond Knopp committed
3353 3354
#endif
  }
3355

Raymond Knopp's avatar
 
Raymond Knopp committed
3356
  // Sleep to allow all threads to setup
Raymond Knopp's avatar
 
Raymond Knopp committed
3357
  sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3358

3359

3360

3361
#ifndef EXMIMO
3362

Raymond Knopp's avatar
 
Raymond Knopp committed
3363
#ifndef USRP_DEBUG
3364
  if (mode!=loop_through_memory)
navid's avatar
navid committed
3365 3366 3367
    if (openair0.trx_start_func(&openair0) != 0 ) 
      LOG_E(HW,"Could not start the device\n");

Raymond Knopp's avatar
 
Raymond Knopp committed
3368
#endif
3369

3370 3371
#endif

3372
  printf("Sending sync to all threads\n");
3373

Raymond Knopp's avatar
 
Raymond Knopp committed
3374
  pthread_mutex_lock(&sync_mutex);
3375
  sync_var=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3376 3377
  pthread_cond_broadcast(&sync_cond);
  pthread_mutex_unlock(&sync_mutex);
3378

Raymond Knopp's avatar
 
Raymond Knopp committed
3379 3380 3381
  // wait for end of program
  printf("TYPE <CTRL-C> TO TERMINATE\n");
  //getchar();
3382 3383

#if defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
3384 3385
  printf("Entering ITTI signals handler\n");
  itti_wait_tasks_end();
3386
  oai_exit=1;
3387
#else
3388

Raymond Knopp's avatar
 
Raymond Knopp committed
3389 3390
  while (oai_exit==0)
    rt_sleep_ns(FRAME_PERIOD);
3391

3392
#endif
3393

Raymond Knopp's avatar
 
Raymond Knopp committed
3394
  // stop threads
3395
#ifdef XFORMS
Raymond Knopp's avatar
 
Raymond Knopp committed
3396
  printf("waiting for XFORMS thread\n");
3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410

  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++) {
3411 3412 3413 3414
	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
3415
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
3416
    }
3417 3418
  }

3419 3420
#endif

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3423 3424
  // cleanup
  if (UE_flag == 1) {
3425
#ifdef EXMIMO
3426
#ifdef RTAI
3427
    rt_thread_join(main_ue_thread);
3428
#else
3429
    pthread_join(main_ue_thread,&status);
3430 3431
#endif
#ifdef DLSCH_THREAD
Raymond Knopp's avatar
 
Raymond Knopp committed
3432 3433
    cleanup_dlsch_threads();
    cleanup_rx_pdsch_thread();
3434
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3435
#endif
3436
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
3437
#ifdef DEBUG_THREADS
Raymond Knopp's avatar
 
Raymond Knopp committed
3438
    printf("Joining eNB_thread ...");
Raymond Knopp's avatar
 
Raymond Knopp committed
3439
#endif
3440
#ifdef RTAI
3441
    rt_thread_join(main_eNB_thread);
3442
#else
3443 3444
    int *eNB_thread_status_p;
    int result = pthread_join( main_eNB_thread, (void**)&eNB_thread_status_p );
Raymond Knopp's avatar
 
Raymond Knopp committed
3445
#ifdef DEBUG_THREADS
3446

3447
    if (result != 0) {
3448
      printf( "\nError joining main_eNB_thread.\n" );
3449
    } else {
3450 3451 3452 3453 3454
      if (eNB_thread_status_p) {
        printf( "status %d\n", *eNB_thread_status_p );
      } else {
        printf( "The thread was killed. No status available.\n");
      }
3455
    }
3456

3457 3458
#else
    UNUSED(result);
3459 3460
#endif // DEBUG_THREADS
#endif // RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3461

Raymond Knopp's avatar
 
Raymond Knopp committed
3462 3463 3464
    if (multi_thread>0) {
      printf("Killing eNB processing threads\n");
      kill_eNB_proc();
Raymond Knopp's avatar
 
Raymond Knopp committed
3465

Raymond Knopp's avatar
 
Raymond Knopp committed
3466
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3467
  }
3468

3469
#ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
3470
  //cleanup_pdcp_thread();
3471 3472
#endif

3473
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3474
  stop_rt_timer();
3475
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3476 3477
  pthread_cond_destroy(&sync_cond);
  pthread_mutex_destroy(&sync_mutex);
3478

3479

3480
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3481
  printf("stopping card\n");
3482
  openair0_stop(0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3483 3484
  printf("closing openair0_lib\n");
  openair0_close();
navid's avatar
navid committed
3485 3486
#else
  openair0.trx_end_func(&openair0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3487
#endif
3488 3489

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3490 3491 3492
  printf("waiting for EMOS thread\n");
  pthread_cancel(thread3);
  pthread_join(thread3,&status);
jiangx's avatar
jiangx committed
3493 3494 3495
  printf("waiting for GPS thread\n");
  pthread_cancel(thread4);
  pthread_join(thread4,&status);
3496 3497 3498
#endif

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3499 3500
  error_code = rtf_destroy(CHANSOUNDER_FIFO_MINOR);
  printf("[OPENAIR][SCHED][CLEANUP] EMOS FIFO closed, error_code %d\n", error_code);
3501 3502
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3503
  if (ouput_vcd)
3504
    VCD_SIGNAL_DUMPER_CLOSE();
3505

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3506
#ifdef OPENAIR2
3507

3508
  if (opt_enabled == 1)
3509
    terminate_opt();
3510

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3511
#endif
3512

Raymond Knopp's avatar
 
Raymond Knopp committed
3513
  logClean();
3514

Raymond Knopp's avatar
 
Raymond Knopp committed
3515 3516
  return 0;
}
3517 3518


3519 3520 3521
/* 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
3522
   antennas are mapped to successive RF chains on the same card. */
3523 3524
int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs])
{
3525

3526
  int i, CC_id;
3527
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3528
  uint16_t N_TA_offset = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3529 3530
#else
  int j;
Raymond Knopp's avatar
 
Raymond Knopp committed
3531
#endif
3532
  LTE_DL_FRAME_PARMS *frame_parms;
3533

Raymond Knopp's avatar
 
Raymond Knopp committed
3534

3535 3536
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    if (phy_vars_eNB[CC_id]) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3537 3538
      frame_parms = &(phy_vars_eNB[CC_id]->lte_frame_parms);
      printf("setup_eNB_buffers: frame_parms = %p\n",frame_parms);
3539
    } else {
3540 3541
      printf("phy_vars_eNB[%d] not initialized\n", CC_id);
      return(-1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3542
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3543

3544
#ifndef EXMIMO
3545

3546 3547
    if (frame_parms->frame_type == TDD) {
      if (frame_parms->N_RB_DL == 100)
3548
        N_TA_offset = 624;
3549
      else if (frame_parms->N_RB_DL == 50)
3550
        N_TA_offset = 624/2;
3551
      else if (frame_parms->N_RB_DL == 25)
3552
        N_TA_offset = 624/4;
Raymond Knopp's avatar
 
Raymond Knopp committed
3553
    }
3554

Raymond Knopp's avatar
 
Raymond Knopp committed
3555
#endif
3556 3557


3558 3559 3560



Raymond Knopp's avatar
 
Raymond Knopp committed
3561
    // replace RX signal buffers with mmaped HW versions
3562
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3563 3564 3565
    openair0_cfg[CC_id].tx_num_channels = 0;
    openair0_cfg[CC_id].rx_num_channels = 0;

3566
    for (i=0; i<frame_parms->nb_antennas_rx; i++) {
3567 3568 3569
      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];
3570

3571
      if (openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i]) {
3572 3573 3574 3575 3576 3577
        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++;
3578
      }
3579

3580
      printf("rxdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]);
3581 3582 3583 3584

      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;
3585
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
3586
    }
3587 3588

    for (i=0; i<frame_parms->nb_antennas_tx; i++) {
3589 3590 3591
      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];
3592

3593
      if (openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i]) {
3594 3595 3596 3597 3598 3599
        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++;
3600
      }
3601

3602
      printf("txdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3603 3604 3605 3606

      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;
3607
      }
3608
    }
3609

3610
#else // not EXMIMO
3611 3612 3613
    rxdata = (int32_t**)malloc16(frame_parms->nb_antennas_rx*sizeof(int32_t*));
    txdata = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*));

3614
    for (i=0; i<frame_parms->nb_antennas_rx; i++) {
3615
      free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]);
3616
      rxdata[i] = (int32_t*)(32 + malloc16(32+openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation
3617
      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
3618
      memset(rxdata[i], 0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t));
3619
      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);
3620
      
Raymond Knopp's avatar
 
Raymond Knopp committed
3621
    }
3622 3623

    for (i=0; i<frame_parms->nb_antennas_tx; i++) {
3624
      free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3625
      txdata[i] = (int32_t*)(32 + malloc16(32 + openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation
3626
      phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i] = txdata[i];
3627
      memset(txdata[i],0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t));
3628
      printf("txdata[%d] @ %p\n", i, phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3629

Raymond Knopp's avatar
 
Raymond Knopp committed
3630
    }
3631

Raymond Knopp's avatar
 
Raymond Knopp committed
3632
#endif
3633
  }
3634

3635
  return(0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3636
}
3637

3638
void reset_opp_meas(void) {
3639 3640 3641
  int sfn;
  reset_meas(&softmodem_stats_mt);
  reset_meas(&softmodem_stats_hw);
3642
  
3643 3644 3645 3646 3647 3648
  for (sfn=0; sfn < 10; sfn++) {
    reset_meas(&softmodem_stats_tx_sf[sfn]);
    reset_meas(&softmodem_stats_rx_sf[sfn]);
  }
}

3649 3650
void print_opp_meas(void) {

3651 3652 3653
  int sfn=0;
  print_meas(&softmodem_stats_mt, "Main ENB Thread", NULL, NULL);
  print_meas(&softmodem_stats_hw, "HW Acquisation", NULL, NULL);
3654
  
3655 3656 3657 3658 3659
  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);
  }
}
3660 3661