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

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


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

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

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

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

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

/*! \file lte-softmodem.c
Raymond Knopp's avatar
 
Raymond Knopp committed
31
 * \brief main program to control HW and scheduling
32
 * \author R. Knopp, F. Kaltenberger, Navid Nikaein
Raymond Knopp's avatar
 
Raymond Knopp committed
33 34 35
 * \date 2012
 * \version 0.1
 * \company Eurecom
36
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr
Raymond Knopp's avatar
 
Raymond Knopp committed
37 38 39
 * \note
 * \warning
 */
Raymond Knopp's avatar
 
Raymond Knopp committed
40
#define _GNU_SOURCE
41 42 43 44 45 46 47 48
#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

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

242
openair0_rf_map rf_map[MAX_NUM_CCs];
243

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

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

253 254
FILE *input_fd=NULL;

255

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

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

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

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

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

#endif
301 302

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
324

325
time_stats_t softmodem_stats_mt; // main thread
Raymond Knopp's avatar
 
Raymond Knopp committed
326
time_stats_t softmodem_stats_hw; //  hw acquisition
327 328
time_stats_t softmodem_stats_tx_sf[10]; // total tx time
time_stats_t softmodem_stats_rx_sf[10]; // total rx time
Navid Nikaein's avatar
Navid Nikaein committed
329 330
void reset_opp_meas(void);
void print_opp_meas(void);
331
int transmission_mode=1;
Raymond Knopp's avatar
 
Raymond Knopp committed
332

Raymond Knopp's avatar
 
Raymond Knopp committed
333

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

Lionel Gauthier's avatar
 
Lionel Gauthier committed
351 352 353 354 355 356
# if defined(ENABLE_USE_MME)
int16_t           gtpu_log_level     = LOG_DEBUG;
int16_t           gtpu_log_verbosity = LOG_MED;
int16_t           udp_log_level      = LOG_DEBUG;
int16_t           udp_log_verbosity  = LOG_MED;
#endif
357 358 359
#if defined (ENABLE_SECURITY)
int16_t           osa_log_level      = LOG_INFO;
int16_t           osa_log_verbosity  = LOG_MED;
360
#endif
361

Raymond Knopp's avatar
 
Raymond Knopp committed
362 363 364

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

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

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

383
#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 426 427 428 429 430 431 432 433 434 435
  printf("  -C Set the downlink frequecny for all Component carrier\n");
  printf("  -d Enable soft scope and L1 and L2 stats (Xforms)\n");
  printf("  -F Calibrate the EXMIMO borad, available files: exmimo2_2arxg.lime exmimo2_2brxg.lime \n");
  printf("  -g Set the global log level, valide options: (9:trace, 8/7:debug, 6:info, 4:warn, 3:error)\n");
  printf("  -G Set the global log level \n");
  printf("  -h provides this help message!\n");
  printf("  -K Generate ITTI analyzser logs (similar to wireshark logs but with more details)\n");
  printf("  -m Set the maximum downlink MCS\n");
  printf("  -M IP address of RRH\n");
  printf("  -O eNB configuration file (located in targets/PROJECTS/GENERIC-LTE-EPC/CONF\n");
  printf("  -q Enable processing timing measurement of lte softmodem on per subframe basis \n");
kaltenbe's avatar
kaltenbe committed
436
  printf("  -r Set the PRB, valid values: 6, 25, 50, 100  \n");    
437 438 439 440 441 442
  printf("  -S Skip the missed slots/subframes \n");    
  printf("  -t Set the maximum uplink MCS\n");
  printf("  -U Set the lte softmodem as a UE\n");
  printf("  -W Enable L2 wireshark messages on localhost \n");
  printf("  -V Enable VCD (generated file will be located atopenair_dump_eNB.vcd, read it with target/RT/USER/eNB.gtkw\n");
  printf("  -x Set the transmission mode, valid options: 1 \n"RESET);    
443

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

  oai_exit = 1;

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

  //rt_sleep_ns(FRAME_PERIOD);

  //exit (-1);
}

463

464
#ifdef XFORMS
465

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

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

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

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

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

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

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

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

512
# ifdef ENABLE_XFORMS_WRITE_STATS
513 514

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

519
#endif
520

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

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

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

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

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

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

557
    }
558

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

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

566
# ifdef ENABLE_XFORMS_WRITE_STATS
567

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

582
# endif
583

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

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

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

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

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

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

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

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

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

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

631 632 633

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

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

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

  pthread_exit((void*) arg);

}

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

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

675 676 677
  time_t timer;
  struct tm *now;

678
  struct sched_param sched_param;
679 680

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

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

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

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

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


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

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

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


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

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

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

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

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

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

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

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

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

}
#endif

786 787


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

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

804 805 806 807 808
    LOG_D(EMU,"\n");
  }
}
#endif

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

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
817

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

827 828 829
      itti_receive_msg (TASK_L2L1, &message_p);

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

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

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
883
  return NULL;
884 885 886
}
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
887

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

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

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
906

Raymond Knopp's avatar
 
Raymond Knopp committed
907
    for (aa=0; aa<phy_vars_eNB->lte_frame_parms.nb_antennas_tx; aa++) {
908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925
      if (phy_vars_eNB->lte_frame_parms.Ncp == EXTENDED) {
        PHY_ofdm_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F],
                     dummy_tx_b,
                     phy_vars_eNB->lte_frame_parms.log2_symbol_size,
                     6,
                     phy_vars_eNB->lte_frame_parms.nb_prefix_samples,
                     CYCLIC_PREFIX);
        PHY_ofdm_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F+slot_sizeF],
                     dummy_tx_b+(phy_vars_eNB->lte_frame_parms.samples_per_tti>>1),
                     phy_vars_eNB->lte_frame_parms.log2_symbol_size,
                     6,
                     phy_vars_eNB->lte_frame_parms.nb_prefix_samples,
                     CYCLIC_PREFIX);
      } else {
        normal_prefix_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F],
                          dummy_tx_b,
                          7,
                          &(phy_vars_eNB->lte_frame_parms));
926 927 928 929 930 931
	// 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
932
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
933

934 935 936 937 938 939 940
      // 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++) {
941 942 943 944 945 946 947 948 949
        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
950
#ifdef EXMIMO
951
          ((short*)dummy_tx_b)[2*i]<<4;
952 953
#elif OAI_BLADRF
	((short*)dummy_tx_b)[2*i];
Raymond Knopp's avatar
 
Raymond Knopp committed
954
#else
955
          ((short*)dummy_tx_b)[2*i]<<5;
Raymond Knopp's avatar
 
Raymond Knopp committed
956
#endif
957
	  ((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[1]=
Raymond Knopp's avatar
 
Raymond Knopp committed
958
#ifdef EXMIMO
959 960 961
	    ((short*)dummy_tx_b)[2*i+1]<<4;
#elif OAI_BLADRF
	  ((short*)dummy_tx_b)[2*i+1];
Raymond Knopp's avatar
 
Raymond Knopp committed
962
#else
963
	  ((short*)dummy_tx_b)[2*i+1]<<5;
Raymond Knopp's avatar
 
Raymond Knopp committed
964
#endif
965 966 967 968 969 970 971
     }
     // if S-subframe switch to RX in second subframe
     if (subframe_select(&phy_vars_eNB->lte_frame_parms,subframe) == SF_S) {
       for (i=0; i<len; i++) {
	 phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset++] = 0x00010001;
       }
     }
Raymond Knopp's avatar
 
Raymond Knopp committed
972 973 974 975
    }
  }
}

976 977 978 979 980 981 982 983 984
/* 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
985

986 987 988 989 990 991 992 993 994
/*!
 * \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
995 996

  eNB_proc_t *proc = (eNB_proc_t*)param;
997 998 999 1000 1001 1002
  FILE  *tx_time_file;
  char tx_time_name[101];
  if (opp_enabled == 1) {
    snprintf(tx_time_name, 100,"/tmp/%s_tx_time_thread_sf_%d", "eNB", proc->subframe);
    tx_time_file = fopen(tx_time_name,"w");
  }
1003 1004 1005
  // set default return value
  eNB_thread_tx_status[proc->subframe] = 0;

1006 1007
  MSC_START_USE();

Raymond Knopp's avatar
 
Raymond Knopp committed
1008 1009
#ifdef RTAI
  RT_TASK *task;
1010
  char task_name[8];
Raymond Knopp's avatar
 
Raymond Knopp committed
1011

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

1015 1016 1017
  if (task == NULL) {
    LOG_E(PHY,"[SCHED][eNB] Problem starting eNB_proc_TX thread_index %d (%s)!!!!\n",proc->subframe,task_name);
    return 0;
1018 1019 1020 1021 1022
  } else {
    LOG_I(PHY,"[SCHED][eNB] eNB TX thread CC %d SF %d started with id %p\n",
          proc->CC_id,
          proc->subframe,
          task);
1023
  }
1024

Raymond Knopp's avatar
 
Raymond Knopp committed
1025
#else
1026
#ifdef LOWLATENCY
1027 1028 1029
  struct sched_attr attr;
  unsigned int flags = 0;

1030 1031 1032 1033
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1034

1035
    attr.sched_policy   = SCHED_DEADLINE;
1036 1037
   //attr.sched_runtime  = 0.9 *  1000000; // each tx thread requires 1ms to finish its job
  attr.sched_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); // each tx thread requires 1ms to finish its job
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1038 1039
  attr.sched_deadline = 1   *  1000000; // each tx thread will finish within 1ms
  attr.sched_period   = 1   * 10000000; // each tx thread has a period of 10ms from the starting point
1040

1041 1042 1043 1044
  if (sched_setattr(0, &attr, flags) < 0 ) {
    perror("[SCHED] eNB tx thread: sched_setattr failed\n");
    return &eNB_thread_tx_status[proc->subframe];
  }
1045

1046
  LOG_I( HW, "[SCHED] eNB TX deadline thread %d(Tid %ld) started on CPU %d\n", proc->subframe, gettid(), sched_getcpu() );
1047
#else
1048
  LOG_I( HW, "[SCHED][eNB] TX thread %d started on CPU %d TID %d\n", proc->subframe, sched_getcpu(),gettid() );
1049 1050
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
1051 1052 1053 1054 1055 1056 1057 1058
#endif

  mlockall(MCL_CURRENT | MCL_FUTURE);

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

1059
  while (!oai_exit) {
1060

1061
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe), 0 );
1062

1063
    if (pthread_mutex_lock(&proc->mutex_tx) != 0) {
1064
      LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc %d\n", proc->subframe );
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1065
      exit_fun("nothing to add");
1066
      break;
1067
    }
1068

1069
    while (proc->instance_cnt_tx < 0) {
1070 1071 1072
      // 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
1073
    }
1074

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

1081 1082
    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 );
1083 1084 1085
    start_meas( &softmodem_stats_tx_sf[proc->subframe] );

    if (oai_exit) break;
1086

1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098
    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;
      }
1099 1100
      /* wait for our turn or oai_exit */
      while (sync_phy_proc[proc->subframe].phy_proc_CC_id != proc->CC_id && !oai_exit) {
1101 1102 1103
        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
1104

1105 1106 1107
      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");
1108 1109
      }

1110 1111 1112
      if (oai_exit)
        break;

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

1115
      /* we're done, let the next one proceed */
1116 1117 1118 1119 1120
      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;
      }
1121 1122 1123 1124
      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) {
1125
        LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc %d\n", proc->subframe);
1126 1127 1128
        exit_fun("nothing to add");
        break;
      }
1129
    }
1130

1131
    do_OFDM_mod_rt( proc->subframe_tx, PHY_vars_eNB_g[0][proc->CC_id] );
1132

1133 1134 1135 1136 1137
    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
1138

1139 1140 1141 1142 1143 1144 1145 1146 1147
    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++;
1148

1149 1150
    if (proc->frame_tx==1024)
      proc->frame_tx=0;
1151
    stop_meas( &softmodem_stats_tx_sf[proc->subframe] );
1152 1153 1154 1155 1156 1157 1158
#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 
1159 1160
    print_meas_now(&softmodem_stats_tx_sf[proc->subframe],"eNB_TX_SF",proc->subframe, tx_time_file);

1161 1162
  }

1163 1164


1165
  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
1166

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

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

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


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

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

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

1207 1208
  MSC_START_USE();

Raymond Knopp's avatar
 
Raymond Knopp committed
1209 1210
#ifdef RTAI
  RT_TASK *task;
1211
  char task_name[8];
Raymond Knopp's avatar
 
Raymond Knopp committed
1212

1213
  sprintf(task_name,"RXC%1dS%1d",proc->CC_id,proc->subframe);
Raymond Knopp's avatar
 
Raymond Knopp committed
1214 1215 1216
  task = rt_task_init_schmod(nam2num(task_name), 0, 0, 0, SCHED_FIFO, 0xF);

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1226
#else
1227
#ifdef LOWLATENCY
1228 1229 1230
  struct sched_attr attr;
  unsigned int flags = 0;

1231 1232 1233 1234
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1235

Navid Nikaein's avatar
Navid Nikaein committed
1236
  /* This creates a 2ms reservation every 10ms period*/
1237
  attr.sched_policy = SCHED_DEADLINE;
1238
  attr.sched_runtime  = (uint64_t)(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); // each tx thread requires 1ms to finish its job
1239
  attr.sched_deadline = 1   *  1000000; // each rx thread will finish within 2ms
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1240
  attr.sched_period   = 1   * 10000000; // each rx thread has a period of 10ms from the starting point
1241 1242

  if (sched_setattr(0, &attr, flags) < 0 ) {
1243
    perror("[SCHED] eNB RX sched_setattr failed\n");
1244
    return &eNB_thread_rx_status[proc->subframe];
1245
  }
1246

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

  mlockall(MCL_CURRENT | MCL_FUTURE);

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

1259
  while (!oai_exit) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1260

1261
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 0 );
1262

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

1269
    while (proc->instance_cnt_rx < 0) {
1270 1271 1272
      // 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
1273
    }
1274 1275 1276 1277 1278 1279 1280

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

1281 1282
    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 );
1283
    start_meas( &softmodem_stats_rx_sf[proc->subframe] );
1284

Raymond Knopp's avatar
 
Raymond Knopp committed
1285
    if (oai_exit) break;
1286

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

1290
      phy_procedures_eNB_RX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay );
Raymond Knopp's avatar
 
Raymond Knopp committed
1291
    }
1292 1293

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

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

    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
1309
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1310 1311

    proc->frame_rx++;
1312

Raymond Knopp's avatar
 
Raymond Knopp committed
1313 1314
    if (proc->frame_rx==1024)
      proc->frame_rx=0;
1315

1316
    stop_meas( &softmodem_stats_rx_sf[proc->subframe] );
1317 1318 1319 1320 1321 1322 1323
#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  
1324
    print_meas_now(&softmodem_stats_rx_sf[proc->subframe],"eNB_RX_SF",proc->subframe, rx_time_file);
Raymond Knopp's avatar
 
Raymond Knopp committed
1325
  }
1326

1327
  //stop_meas( &softmodem_stats_rx_sf[proc->subframe] );
1328
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 0 );
1329

Raymond Knopp's avatar
 
Raymond Knopp committed
1330
#ifdef HARD_RT
Raymond Knopp's avatar
 
Raymond Knopp committed
1331 1332 1333 1334
  rt_make_soft_real_time();
#endif

#ifdef DEBUG_THREADS
1335
  printf( "Exiting eNB thread RX %d\n", proc->subframe );
Raymond Knopp's avatar
 
Raymond Knopp committed
1336 1337 1338 1339
#endif
  // clean task
#ifdef RTAI
  rt_task_delete(task);
Raymond Knopp's avatar
 
Raymond Knopp committed
1340 1341
#endif

1342 1343
  eNB_thread_rx_status[proc->subframe] = 0;
  return &eNB_thread_rx_status[proc->subframe];
Raymond Knopp's avatar
 
Raymond Knopp committed
1344 1345 1346 1347
}



Raymond Knopp's avatar
 
Raymond Knopp committed
1348

1349 1350
void init_eNB_proc(void)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1351
  int i;
Raymond Knopp's avatar
 
Raymond Knopp committed
1352 1353
  int CC_id;

1354 1355 1356 1357
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    for (i=0; i<NUM_ENB_THREADS; i++) {
      // set the stack size
      pthread_attr_init( &attr_eNB_proc_tx[CC_id][i] );
1358

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

1362
      pthread_attr_init( &attr_eNB_proc_rx[CC_id][i] );
1363

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

1367
#ifndef LOWLATENCY
1368
      // set the kernel scheduling policy and priority
Raymond Knopp's avatar
 
Raymond Knopp committed
1369 1370 1371 1372 1373 1374
      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);
1375
      printf("Setting OS scheduler to SCHED_FIFO for eNB [cc%d][thread%d] \n",CC_id, i);
1376
#endif
1377 1378 1379
      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
1380
      PHY_vars_eNB_g[0][CC_id]->proc[i].CC_id = CC_id;
1381 1382 1383 1384
      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);
1385 1386 1387 1388
#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 
1389 1390
      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] );
1391
#endif
1392 1393 1394 1395 1396
      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
1397 1398
      PHY_vars_eNB_g[0][CC_id]->proc[i].frame_tx = 0;
      PHY_vars_eNB_g[0][CC_id]->proc[i].frame_rx = 0;
1399
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
1400 1401
      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
1402
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
1403 1404
      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
1405
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1406
    }
1407 1408


1409
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
1410 1411
    // 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
1412

Raymond Knopp's avatar
 
Raymond Knopp committed
1413
    //PHY_vars_eNB_g[0][CC_id]->proc[0].frame_rx = 1023;
Raymond Knopp's avatar
 
Raymond Knopp committed
1414 1415
    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
1416
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
1417 1418
    // 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
1419
    //    PHY_vars_eNB_g[0][CC_id]->proc[7].frame_tx = 1;
Raymond Knopp's avatar
 
Raymond Knopp committed
1420 1421
    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
1422
    //    PHY_vars_eNB_g[0][CC_id]->proc[0].frame_tx = 1;
Raymond Knopp's avatar
 
Raymond Knopp committed
1423
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1424
  }
1425 1426 1427 1428 1429 1430 1431

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

1434 1435 1436 1437 1438 1439
/*!
 * \brief Terminate eNB TX and RX threads.
 */
void kill_eNB_proc(void)
{
  int *status;
Raymond Knopp's avatar
 
Raymond Knopp committed
1440

1441 1442
  for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++)
    for (int i=0; i<NUM_ENB_THREADS; i++) {
1443

Raymond Knopp's avatar
 
Raymond Knopp committed
1444
#ifdef DEBUG_THREADS
1445
      printf( "Killing TX CC_id %d thread %d\n", CC_id, i );
Raymond Knopp's avatar
 
Raymond Knopp committed
1446
#endif
1447 1448 1449

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1457
#ifdef DEBUG_THREADS
1458

1459 1460 1461 1462 1463 1464 1465 1466 1467
      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" );
        }
      }
1468

1469 1470
#else
      UNUSED(result)
Raymond Knopp's avatar
 
Raymond Knopp committed
1471
#endif
1472

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

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

1485 1486
#ifdef DEBUG_THREADS

1487 1488 1489 1490 1491 1492 1493 1494 1495
      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" );
        }
      }
1496

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

      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
1505
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1506 1507 1508
}


Raymond Knopp's avatar
 
Raymond Knopp committed
1509 1510


1511

Raymond Knopp's avatar
 
Raymond Knopp committed
1512

1513 1514 1515 1516 1517 1518
/*!
 * \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 )
1519
{
1520 1521
  UNUSED(arg);
  static int eNB_thread_status;
1522

1523
  unsigned char slot;
1524
#ifdef EXMIMO
1525
  slot=0;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1526
  RTIME time_in;
Raymond Knopp's avatar
 
Raymond Knopp committed
1527
  volatile unsigned int *DAQ_MBOX = openair0_daq_cnt();
Raymond Knopp's avatar
 
Raymond Knopp committed
1528 1529
  int mbox_target=0,mbox_current=0;
  int hw_slot,delay_cnt;
Raymond Knopp's avatar
 
Raymond Knopp committed
1530 1531
  int diff;
  int ret;
1532
  int first_run=1;
Raymond Knopp's avatar
 
Raymond Knopp committed
1533
#else
1534 1535 1536
  // the USRP implementation operates on subframes, not slots
  // one subframe consists of one even and one odd slot
  slot = 1;
1537
  int spp;
1538
  int tx_launched = 0;
1539 1540 1541

  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
1542

1543
  int hw_subframe = 0; // 0..NUM_ENB_THREADS-1 => 0..9
1544
  spp = openair0_cfg[0].samples_per_packet;
1545
  unsigned int rx_pos = 0;
1546
  unsigned int tx_pos = 0; //spp*tx_delay;
Raymond Knopp's avatar
 
Raymond Knopp committed
1547
#endif
1548
  int CC_id=0;	
1549
  struct timespec trx_time0, trx_time1, trx_time2;
1550

1551
#ifdef RTAI
1552
  RT_TASK* task = rt_task_init_schmod(nam2num("eNBmain"), 0, 0, 0, SCHED_FIFO, 0xF);
1553
#else
1554
#ifdef LOWLATENCY
1555 1556 1557
  struct sched_attr attr;
  unsigned int flags = 0;

Raymond Knopp's avatar
 
Raymond Knopp committed
1558 1559 1560 1561
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1562

1563
  /* This creates a .2 ms  reservation */
Raymond Knopp's avatar
 
Raymond Knopp committed
1564
  attr.sched_policy = SCHED_DEADLINE;
1565 1566 1567
  attr.sched_runtime  = (0.2 * 100) * 10000;
  attr.sched_deadline = (0.9 * 100) * 10000;
  attr.sched_period   = 1 * 1000000;
1568

Lionel Gauthier's avatar
Lionel Gauthier committed
1569

Raymond Knopp's avatar
 
Raymond Knopp committed
1570 1571 1572 1573
  /* 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");
     }*/
1574

1575
  if (sched_setattr(0, &attr, flags) < 0 ) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1576 1577 1578 1579
    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",
1580
          gettid(),sched_getcpu());
Raymond Knopp's avatar
 
Raymond Knopp committed
1581
  }
1582

1583
#endif
1584 1585
#endif

1586 1587 1588 1589 1590
  // stop early, if an exit is requested
  // FIXME really neccessary?
  if (oai_exit)
    goto eNB_thread_cleanup;

1591
#ifdef RTAI
1592
  printf( "[SCHED][eNB] Started eNB main thread (id %p)\n", task );
Raymond Knopp's avatar
 
Raymond Knopp committed
1593
#else
1594
  printf( "[SCHED][eNB] Started eNB main thread on CPU %d TID %d\n", sched_getcpu(), gettid());
1595 1596 1597
#endif

#ifdef HARD_RT
1598
  rt_make_hard_real_time();
1599 1600
#endif

1601 1602 1603 1604 1605 1606 1607 1608
  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;
1609

1610 1611
  printf( "waiting for sync (eNB_thread)\n" );
  pthread_mutex_lock( &sync_mutex );
1612

1613 1614
  while (sync_var<0)
    pthread_cond_wait( &sync_cond, &sync_mutex );
1615

1616
  pthread_mutex_unlock(&sync_mutex);
1617

1618
  int frame = 0;
1619

1620 1621
  while (!oai_exit) {
    start_meas( &softmodem_stats_mt );
Raymond Knopp's avatar
 
Raymond Knopp committed
1622

1623
#ifdef EXMIMO
1624 1625
    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]);
1626 1627
    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);
1628 1629 1630 1631
    //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];
1632

1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643
    //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;
1644

1645
      if (diff<0)
1646
        diff = diff + 150;
1647

1648 1649 1650 1651
      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)))) {
1652

1653 1654 1655 1656
      // 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);
      
1657
      if (exit_missed_slots==1) {
1658 1659
        stop_meas(&softmodem_stats_mt);
        exit_fun("[HW][eNB] missed slot");
1660
      } else {
1661
        num_missed_slots++;
1662
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_MISSED_SLOTS_ENB,num_missed_slots );
1663
      }
1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685

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

    
1686
    }
1687

1688
    if (diff>8)
1689 1690
      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);
1691

1692 1693
    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);
1694 1695

    delay_cnt = 0;
1696

1697 1698 1699 1700
    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);
1701
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP,1);
1702
      ret = rt_sleep_ns(diff*DAQ_PERIOD);
1703 1704
      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);
1705

1706 1707
      if (ret)
        LOG_D(HW,"eNB Frame %d, time %llu: rt_sleep_ns returned %d\n",frame, time_in);
1708

Raymond Knopp's avatar
 
Raymond Knopp committed
1709
      hw_slot = (((((volatile unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15;
1710 1711 1712
      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());
1713
      delay_cnt++;
1714

1715 1716 1717 1718 1719
      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");
      }
1720

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1723
      if ((mbox_current>=135) && (mbox_target<15)) //handle the frame wrap-arround
1724
        diff = 150-mbox_current+mbox_target;
Raymond Knopp's avatar
 
Raymond Knopp committed
1725
      else if ((mbox_current<15) && (mbox_target>=135))
1726
        diff = -150+mbox_target-mbox_current;
Raymond Knopp's avatar
 
Raymond Knopp committed
1727
      else
1728 1729
        diff = mbox_target - mbox_current;
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1730

1731
#else  // EXMIMO
1732 1733
    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 );
1734
    tx_launched = 0;
1735

1736
    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
1737

1738
      unsigned int rxs;
Raymond Knopp's avatar
 
Raymond Knopp committed
1739
#ifndef USRP_DEBUG
1740 1741 1742
      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
1743

1744
      clock_gettime( CLOCK_MONOTONIC, &trx_time0 );
1745

1746
       start_meas( &softmodem_stats_hw );
1747

1748
      openair0_timestamp timestamp;
1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760
      int i=0;
      // prepare rx buffer pointers
      for (i=0; i<PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx; i++){
        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,
				     i);
      }
1761 1762
      stop_meas( &softmodem_stats_hw );
      clock_gettime( CLOCK_MONOTONIC, &trx_time1 );
Raymond Knopp's avatar
 
Raymond Knopp committed
1763

1764 1765 1766 1767
      if (frame > 10){ 
	if (rxs != spp)
	  exit_fun( "problem receiving samples" );
      }
1768
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
1769

1770 1771 1772
      // Transmit TX buffer based on timestamp from RX


1773 1774 1775 1776 1777 1778 1779 1780 1781
if (frame > 50) {
      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*)&rxdata[i][tx_pos];
		//printf("tx_pos %d ts %d, ts_offset %d txp[i] %p, ap %d\n", tx_pos,  timestamp, (timestamp+(tx_delay*spp)-tx_forward_nsamps),txp[i], i);
	  // if symb_written < spp ==> error 
	  openair0.trx_write_func(&openair0,
                                (timestamp+(openair0_cfg[card].tx_delay*spp)-openair0_cfg[card].tx_forward_nsamps),
1782 1783
                                txp,
                                spp,
1784
                                i,
1785
                                1);
1786 1787
        }
	}
Raymond Knopp's avatar
 
Raymond Knopp committed
1788

1789
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, timestamp&0xffffffff );
1790
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp+(openair0_cfg[card].tx_delay*spp)-openair0_cfg[card].tx_forward_nsamps)&0xffffffff );
1791 1792 1793 1794

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

1795
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE,0);
1796 1797 1798 1799 1800 1801 1802 1803
#else
      // USRP_DEBUG is active
      rt_sleep_ns(1000000);
#endif

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

1805
        for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833
          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;

1834 1835
      if (tx_pos >= openair0_cfg[card].samples_per_frame)
        tx_pos -= openair0_cfg[card].samples_per_frame;
1836 1837
    }

1838 1839
    if (rx_pos >= openair0_cfg[card].samples_per_frame)
      rx_pos -= openair0_cfg[card].samples_per_frame;
1840

Raymond Knopp's avatar
 
Raymond Knopp committed
1841 1842

#endif // USRP
1843

1844
    if (oai_exit) break;
Raymond Knopp's avatar
 
Raymond Knopp committed
1845

1846 1847 1848 1849 1850
    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;
1851

1852 1853
      if (time_diff < timing_info.time_min)
        timing_info.time_min = time_diff;
1854

1855 1856
      if (time_diff > timing_info.time_max)
        timing_info.time_max = time_diff;
1857

1858 1859 1860 1861 1862 1863
      timing_info.time_avg += time_diff;
    }

    timing_info.n_samples++;

    if ((slot&1) == 1) {
1864
      // odd slot
1865
#ifdef EXMIMO
1866
      int sf = ((slot>>1)+1)%10;
Raymond Knopp's avatar
 
Raymond Knopp committed
1867
#else
1868
      int sf = hw_subframe;
Raymond Knopp's avatar
 
Raymond Knopp committed
1869
#endif
1870 1871

      for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1872 1873
#ifdef EXMIMO

1874 1875
        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);
1876 1877
        } 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);
1878 1879
          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);
1880

1881 1882 1883 1884
          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);
            }
1885
          } else {
1886 1887 1888 1889
            LOG_W(PHY,"[eNB] Frame %d, eNB TX thread %d busy!!\n",PHY_vars_eNB_g[0][CC_id]->proc[sf].frame_tx,sf);
            exit_fun("nothing to add");
          }
        }
1890

Raymond Knopp's avatar
 
Raymond Knopp committed
1891 1892
#endif

1893 1894 1895 1896 1897
        if (pthread_mutex_lock(&PHY_vars_eNB_g[0][CC_id]->proc[sf].mutex_rx) != 0) {
          LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB RX thread %d (IC %d)\n", sf, PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_rx );
          exit_fun( "error locking mutex_rx" );
          break;
        }
Raymond Knopp's avatar
 
Raymond Knopp committed
1898

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

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

1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914
        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
1915
      }
1916 1917 1918 1919
    }

#ifdef EXMIMO
    slot++;
1920

1921 1922 1923 1924
    if (slot == 20) {
      frame++;
      slot = 0;
    }
1925

Raymond Knopp's avatar
 
Raymond Knopp committed
1926
#else
1927 1928
    hw_subframe++;
    slot += 2;
1929

1930
    if (hw_subframe == NUM_ENB_THREADS) {
1931
      // the radio frame is complete, start over
1932 1933 1934 1935
      hw_subframe = 0;
      frame++;
      slot = 1;
    }
1936 1937

#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1938

1939
#if defined(ENABLE_ITTI)
1940
    itti_update_lte_time( frame, slot );
1941
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1942
  }
1943 1944

eNB_thread_cleanup:
Raymond Knopp's avatar
 
Raymond Knopp committed
1945
#ifdef DEBUG_THREADS
1946
  printf( "eNB_thread: finished, ran %d times.\n", frame );
Raymond Knopp's avatar
 
Raymond Knopp committed
1947
#endif
1948

1949
#ifdef HARD_RT
Raymond Knopp's avatar
 
Raymond Knopp committed
1950
  rt_make_soft_real_time();
1951 1952
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
1953
#ifdef DEBUG_THREADS
1954
  printf( "Exiting eNB_thread ..." );
Raymond Knopp's avatar
 
Raymond Knopp committed
1955 1956
#endif
  // clean task
1957
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
1958
  rt_task_delete(task);
1959
#endif
1960 1961 1962

  eNB_thread_status = 0;
  return &eNB_thread_status;
Raymond Knopp's avatar
 
Raymond Knopp committed
1963
}
1964

1965

Raymond Knopp's avatar
 
Raymond Knopp committed
1966

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1967

1968 1969
static void get_options (int argc, char **argv)
{
1970 1971 1972
  int c;
  //  char                          line[1000];
  //  int                           l;
1973
  int k,i;//,j,k;
1974
#if defined(OAI_USRP) || defined(CPRIGW)
1975
  int clock_src;
1976
#endif
1977 1978 1979 1980 1981
  int CC_id;
#ifdef EXMIMO
  char rxg_fname[256], line[1000];
  FILE *rxg_fd;
  int l;
1982
#endif
1983 1984 1985



1986 1987

  const Enb_properties_array_t *enb_properties;
1988

1989 1990 1991 1992 1993 1994 1995
  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,
1996
    LONG_OPTION_NO_L2_CONNECT,
Raymond Knopp's avatar
 
Raymond Knopp committed
1997
    LONG_OPTION_CALIB_PRACH_TX,
1998 1999
    LONG_OPTION_RXGAIN,
    LONG_OPTION_TXGAIN,
2000
    LONG_OPTION_SCANCARRIER,
2001 2002 2003
    LONG_OPTION_MAXPOWER,
    LONG_OPTION_DUMP_FRAME,
    LONG_OPTION_LOOPMEMORY
2004
  };
2005

2006 2007 2008 2009 2010 2011 2012
  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
2013 2014 2015 2016
    {"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},
2017
    {"ue-max-power",   required_argument,  NULL, LONG_OPTION_MAXPOWER},
2018 2019
    {"ue-dump-frame", no_argument, NULL, LONG_OPTION_DUMP_FRAME},
    {"loop-memory", required_argument, NULL, LONG_OPTION_LOOPMEMORY},
2020 2021 2022
    {NULL, 0, NULL, 0}
  };

2023
  while ((c = getopt_long (argc, argv, "C:dK:g:F:G:hqO:m:SUVRM:r:P:Ws:t:x:",long_options,NULL)) != -1) {
2024
    switch (c) {
2025 2026 2027 2028 2029
    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];

2030 2031 2032 2033
    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;
2034

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

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

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

2053 2054 2055
    case LONG_OPTION_DEBUG_UE_PRACH:
      mode = debug_prach;
      break;
2056

2057 2058 2059
    case LONG_OPTION_NO_L2_CONNECT:
      mode = no_L2_connect;
      break;
2060

Raymond Knopp's avatar
 
Raymond Knopp committed
2061 2062 2063 2064
    case LONG_OPTION_CALIB_PRACH_TX:
      mode = calib_prach_tx;
      break;

2065
    case LONG_OPTION_RXGAIN:
2066 2067
      for (i=0; i<4; i++)
        rx_gain[0][i] = atof(optarg);
2068

2069
      break;
2070

2071 2072 2073
    case LONG_OPTION_TXGAIN:
      for (i=0; i<4; i++)
        tx_gain[0][i] = atof(optarg);
2074

2075
      break;
2076

2077 2078 2079 2080 2081
    case LONG_OPTION_SCANCARRIER:
      UE_scan_carrier=1;

      break;

2082 2083 2084 2085 2086 2087 2088 2089 2090 2091
    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;

2092 2093 2094
    case 'M':
#ifdef ETHERNET
      strcpy(rrh_eNB_ip,optarg);
2095
#endif
2096
      break;
2097

2098
    case 'C':
2099 2100 2101 2102 2103 2104
      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]);
2105
      }
2106

2107
      UE_scan=0;
2108

2109
      break;
2110

2111 2112 2113 2114
    case 'd':
#ifdef XFORMS
      do_forms=1;
      printf("Running with XFORMS!\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2115
#endif
2116
      break;
2117

2118 2119 2120
    case 'K':
#if defined(ENABLE_ITTI)
      itti_dump_file = strdup(optarg);
2121
#else
2122
      printf("-K option is disabled when ENABLE_ITTI is not defined\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2123
#endif
2124
      break;
2125

2126 2127 2128
    case 'O':
      conf_config_file_name = optarg;
      break;
2129

2130 2131 2132
    case 'U':
      UE_flag = 1;
      break;
2133

2134 2135 2136
    case 'm':
      target_dl_mcs = atoi (optarg);
      break;
2137

2138 2139 2140
    case 't':
      target_ul_mcs = atoi (optarg);
      break;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2141
#ifdef OPENAIR2
2142

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

2161
    case 'P':
2162 2163
      opt_type = OPT_PCAP;
      opt_enabled=1;
2164 2165 2166 2167 2168

      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");
2169
      } else {
2170 2171 2172
        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);
2173
      }
2174 2175

      break;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2176
#endif
2177

Raymond Knopp's avatar
 
Raymond Knopp committed
2178 2179 2180
    case 'V':
      ouput_vcd = 1;
      break;
2181

Raymond Knopp's avatar
 
Raymond Knopp committed
2182
    case  'q':
Raymond Knopp's avatar
 
Raymond Knopp committed
2183 2184
      opp_enabled = 1;
      break;
2185

Raymond Knopp's avatar
 
Raymond Knopp committed
2186 2187 2188
    case  'R' :
      online_log_messages =1;
      break;
2189

Raymond Knopp's avatar
 
Raymond Knopp committed
2190
    case 'r':
2191
      UE_scan = 0;
2192

2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218
      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
2219
      }
2220

2221
      break;
2222

Raymond Knopp's avatar
 
Raymond Knopp committed
2223
    case 's':
2224
#if defined(OAI_USRP) || defined(CPRIGW)
Raymond Knopp's avatar
 
Raymond Knopp committed
2225 2226

      clock_src = atoi(optarg);
2227

Raymond Knopp's avatar
 
Raymond Knopp committed
2228
      if (clock_src == 0) {
2229 2230 2231 2232 2233
        //  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
2234
      }
2235

Raymond Knopp's avatar
 
Raymond Knopp committed
2236 2237 2238 2239
#else
      printf("Note: -s not defined for ExpressMIMO2\n");
#endif
      break;
2240

2241 2242 2243 2244
    case 'S':
      exit_missed_slots=0;
      printf("Skip exit for missed slots\n");
      break;
2245

2246
    case 'g':
Raymond Knopp's avatar
 
Raymond Knopp committed
2247
      glog_level=atoi(optarg); // value between 1 - 9
2248
      break;
2249 2250

    case 'F':
2251
#ifdef EXMIMO
2252 2253
      sprintf(rxg_fname,"%srxg.lime",optarg);
      rxg_fd = fopen(rxg_fname,"r");
2254

2255
      if (rxg_fd) {
2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273
        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);

2274
#endif
2275
      break;
2276

2277 2278 2279
    case 'G':
      glog_verbosity=atoi(optarg);// value from 0, 0x5, 0x15, 0x35, 0x75
      break;
2280

2281 2282
    case 'x':
      transmission_mode = atoi(optarg);
2283

2284
      if (transmission_mode > 2) {
2285 2286
        printf("Transmission mode > 2 (%d) not supported for the moment\n",transmission_mode);
        exit(-1);
2287
      }
2288

2289
      break;
2290 2291 2292 2293
    case 'h':
      help ();
      exit (-1);
       
Raymond Knopp's avatar
 
Raymond Knopp committed
2294
    default:
2295 2296
      help ();
      exit (-1);
Raymond Knopp's avatar
 
Raymond Knopp committed
2297
      break;
2298 2299
    }
  }
2300

Raymond Knopp's avatar
 
Raymond Knopp committed
2301 2302
  if (UE_flag == 0)
    AssertFatal(conf_config_file_name != NULL,"Please provide a configuration file\n");
2303 2304


Raymond Knopp's avatar
 
Raymond Knopp committed
2305
  if ((UE_flag == 0) && (conf_config_file_name != NULL)) {
2306
    int i,j;
2307

Raymond Knopp's avatar
 
Raymond Knopp committed
2308
    NB_eNB_INST = 1;
2309

Raymond Knopp's avatar
 
Raymond Knopp committed
2310 2311
    /* Read eNB configuration file */
    enb_properties = enb_config_init(conf_config_file_name);
2312

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

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

2339

2340
#ifdef OPENAIR2
2341

2342 2343 2344
      init_all_otg(0);
      g_otg->seed = 0;
      init_seeds(g_otg->seed);
2345 2346 2347 2348 2349 2350 2351 2352 2353 2354

      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");
2355
      }
2356

2357
      init_predef_traffic(enb_properties->properties[i]->num_otg_elements, 1);
2358

2359
#endif
2360

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

Raymond Knopp's avatar
 
Raymond Knopp committed
2386
      // adjust the log
2387
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
2388 2389 2390 2391 2392 2393 2394 2395 2396 2397
        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
2398
      } // CC_id
2399
    }// i
2400 2401 2402 2403 2404 2405 2406 2407
  } 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
2408
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
2409
}
2410

2411 2412
int main( int argc, char **argv )
{
Raymond Knopp's avatar
 
Raymond Knopp committed
2413
  int i,aa,card;
Lionel Gauthier's avatar
Lionel Gauthier committed
2414
#if defined (XFORMS) || defined (EMOS) || defined (EXMIMO)
Raymond Knopp's avatar
 
Raymond Knopp committed
2415
  void *status;
2416
#endif
2417

Raymond Knopp's avatar
 
Raymond Knopp committed
2418
  int CC_id;
Raymond Knopp's avatar
 
Raymond Knopp committed
2419
  uint16_t Nid_cell = 0;
2420
  uint8_t  cooperation_flag=0,  abstraction_flag=0;
2421
#ifndef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
2422
  uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2;
2423 2424 2425
#endif

#ifdef ENABLE_TCXO
Raymond Knopp's avatar
 
Raymond Knopp committed
2426
  unsigned int tcxo = 114;
2427 2428
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
2429
#if defined (XFORMS)
2430 2431
  int ret;
#endif
2432
#if defined (EMOS) || (! defined (RTAI))
Raymond Knopp's avatar
 
Raymond Knopp committed
2433
  int error_code;
2434
#endif
2435

2436 2437 2438 2439 2440
#ifdef DEBUG_CONSOLE
  setvbuf(stdout, NULL, _IONBF, 0);
  setvbuf(stderr, NULL, _IONBF, 0);
#endif

2441 2442 2443
  PHY_VARS_UE *UE[MAX_NUM_CCs];

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

2446
  memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
Raymond Knopp's avatar
 
Raymond Knopp committed
2447
  set_latency_target();
2448

2449

2450

2451
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2452 2453
    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 */
2454
    frame_parms[CC_id]->frame_type         = FDD; /* TDD */
Raymond Knopp's avatar
 
Raymond Knopp committed
2455 2456
    frame_parms[CC_id]->tdd_config          = 3;
    frame_parms[CC_id]->tdd_config_S        = 0;
2457 2458
    frame_parms[CC_id]->N_RB_DL             = 100;
    frame_parms[CC_id]->N_RB_UL             = 100;
Raymond Knopp's avatar
 
Raymond Knopp committed
2459
    frame_parms[CC_id]->Ncp                 = NORMAL;
Raymond Knopp's avatar
 
Raymond Knopp committed
2460 2461
    frame_parms[CC_id]->Ncp_UL              = NORMAL;
    frame_parms[CC_id]->Nid_cell            = Nid_cell;
Raymond Knopp's avatar
 
Raymond Knopp committed
2462
    frame_parms[CC_id]->num_MBSFN_config    = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2463 2464 2465
    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
2466
  }
2467

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

2483 2484
  //randominit (0);
  set_taus_seed (0);
Raymond Knopp's avatar
 
Raymond Knopp committed
2485

2486 2487
  if (UE_flag==1) {
    printf("configuring for UE\n");
2488

2489
    set_comp_log(HW,      LOG_INFO,  LOG_HIGH, 1);
2490 2491 2492 2493 2494 2495
    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);
2496
#if defined(ENABLE_ITTI)
2497
    set_comp_log(EMU,     LOG_INFO,   LOG_MED, 1);
2498
# if defined(ENABLE_USE_MME)
2499
    set_comp_log(NAS,     LOG_INFO,   LOG_HIGH, 1);
2500 2501
# endif
#endif
2502 2503
  } else {
    printf("configuring for eNB\n");
2504

2505
    set_comp_log(HW,      hw_log_level, hw_log_verbosity, 1);
2506
#ifdef OPENAIR2
2507 2508 2509 2510 2511
    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);

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

Raymond Knopp's avatar
 
Raymond Knopp committed
2544 2545
  if (ouput_vcd) {
    if (UE_flag==1)
2546
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_UE.vcd");
Raymond Knopp's avatar
 
Raymond Knopp committed
2547
    else
2548
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_eNB.vcd");
Raymond Knopp's avatar
 
Raymond Knopp committed
2549
  }
2550

2551
  if (opp_enabled ==1){
2552
    reset_opp_meas();
2553 2554
  }
  cpuf=get_cpu_freq_GHz();
2555

2556
#if defined(ENABLE_ITTI)
2557

Raymond Knopp's avatar
 
Raymond Knopp committed
2558 2559
  if (UE_flag == 1) {
    log_set_instance_type (LOG_INSTANCE_UE);
2560
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
2561 2562
    log_set_instance_type (LOG_INSTANCE_ENB);
  }
2563

Raymond Knopp's avatar
 
Raymond Knopp committed
2564
  itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, itti_dump_file);
2565
 
2566 2567
  // initialize mscgen log after ITTI
  MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX);
2568 2569
#endif
 
2570
#ifdef OPENAIR2
2571

2572 2573
  if (opt_type != OPT_NONE) {
    radio_type_t radio_type;
2574

2575 2576
    if (frame_parms[0]->frame_type == FDD)
      radio_type = RADIO_TYPE_FDD;
2577
    else
2578
      radio_type = RADIO_TYPE_TDD;
2579

2580 2581 2582
    if (init_opt(in_path, in_ip, NULL, radio_type) == -1)
      LOG_E(OPT,"failed to run OPT \n");
  }
2583

2584
#endif
2585
#ifdef PDCP_USE_NETLINK
Raymond Knopp's avatar
 
Raymond Knopp committed
2586
  netlink_init();
2587 2588
#endif

2589
#if !defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
2590 2591 2592
  // to make a graceful exit when ctrl-c is pressed
  signal(SIGSEGV, signal_handler);
  signal(SIGINT, signal_handler);
2593
#endif
2594 2595

#ifndef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
2596 2597 2598 2599
  check_clock();
#endif

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

2603 2604 2605 2606 2607 2608 2609 2610 2611
    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
2612 2613 2614 2615 2616 2617 2618 2619
    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;
2620 2621
    init_ul_hopping(frame_parms[CC_id]);
    init_frame_parms(frame_parms[CC_id],1);
2622 2623
    //   phy_init_top(frame_parms[CC_id]);
    phy_init_lte_top(frame_parms[CC_id]);
Raymond Knopp's avatar
 
Raymond Knopp committed
2624 2625 2626
  }


2627
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2628
    //init prach for openair1 test
2629
    frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22;
Raymond Knopp's avatar
 
Raymond Knopp committed
2630
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1;
2631
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2632 2633 2634
    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
2635
    // N_ZC = (prach_fmt <4)?839:139;
Raymond Knopp's avatar
 
Raymond Knopp committed
2636
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
2637 2638

  if (UE_flag==1) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2639 2640 2641
    NB_UE_INST=1;
    NB_INST=1;

Raymond Knopp's avatar
 
Raymond Knopp committed
2642 2643
    PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE**));
    PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_UE*)*MAX_NUM_CCs);
2644 2645

    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
2646 2647 2648 2649

      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
2650
#ifndef OPENAIR2
2651 2652 2653 2654 2655 2656 2657 2658 2659

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

2662
#endif
2663 2664 2665


      UE[CC_id]->UE_scan = UE_scan;
2666
      UE[CC_id]->UE_scan_carrier = UE_scan_carrier;
2667 2668 2669
      UE[CC_id]->mode    = mode;

      compute_prach_seq(&UE[CC_id]->lte_frame_parms.prach_config_common,
2670 2671 2672
                        UE[CC_id]->lte_frame_parms.frame_type,
                        UE[CC_id]->X_u);

2673
      UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1234;
2674
#ifndef OPENAIR2
2675
      UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1235;
2676
#endif
2677

2678
#ifdef EXMIMO
2679

2680 2681 2682 2683
      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
2684
      }
2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703

      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
2704
      }
2705

2706
#else
2707
      UE[CC_id]->rx_total_gain_dB =  (int)rx_gain[CC_id][0];
2708
#endif
2709

2710
      UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id];
2711

2712 2713


2714
#ifdef EXMIMO
2715

Raymond Knopp's avatar
 
Raymond Knopp committed
2716
      //N_TA_offset
2717
      if (UE[CC_id]->lte_frame_parms.frame_type == TDD) {
2718 2719 2720 2721 2722 2723 2724 2725
        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
2726
      }
2727

2728
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
2729
      //already taken care of in lte-softmodem
2730
      UE[CC_id]->N_TA_offset = 0;
2731
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2732
    }
2733

Raymond Knopp's avatar
 
Raymond Knopp committed
2734 2735 2736 2737
    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;
2738 2739 2740



Raymond Knopp's avatar
 
Raymond Knopp committed
2741
    //  printf("tx_max_power = %d -> amp %d\n",tx_max_power,get_tx_amp(tx_max_power,tx_max_power));
2742 2743 2744 2745 2746 2747 2748 2749 2750
  } else {
    //this is eNB
    PHY_vars_eNB_g = malloc(sizeof(PHY_VARS_eNB**));
    PHY_vars_eNB_g[0] = malloc(sizeof(PHY_VARS_eNB*));

    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
      PHY_vars_eNB_g[0][CC_id] = init_lte_eNB(frame_parms[CC_id],0,Nid_cell,cooperation_flag,transmission_mode,abstraction_flag);
      PHY_vars_eNB_g[0][CC_id]->CC_id = CC_id;

2751
#ifndef OPENAIR2
2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767

      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
2768

2769
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
2770

2771
      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
2772

2773
#else
2774 2775 2776
      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
2777

2778 2779 2780
      // 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
2781

2782
#endif
2783

2784
#ifdef EXMIMO
2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795

      //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
2796
      }
2797

2798 2799 2800 2801
#else
      //already taken care of in lte-softmodem
      PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 0;
#endif
2802

2803
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
2804 2805


2806 2807 2808 2809 2810 2811 2812 2813 2814
    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;

  }
2815 2816 2817 2818
#ifndef RTAI
  fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx);
  cpuf=get_cpu_freq_GHz();
#endif 
2819

Raymond Knopp's avatar
 
Raymond Knopp committed
2820
  dump_frame_parms(frame_parms[0]);
2821

Raymond Knopp's avatar
 
Raymond Knopp committed
2822
  if(frame_parms[0]->N_RB_DL == 100) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2823
    sample_rate = 30.72e6;
2824
    bw          = 10.0e6;
2825
#ifndef EXMIMO
2826 2827 2828
    openair0_cfg[card].sample_rate=30.72e6;
    openair0_cfg[card].samples_per_packet = 2048;
    openair0_cfg[card].samples_per_frame = 307200; 
2829 2830
    openair0_cfg[card].tx_bw = 10e6;
    openair0_cfg[card].rx_bw = 10e6;
Raymond Knopp's avatar
 
Raymond Knopp committed
2831
    // from usrp_time_offset
2832 2833
    openair0_cfg[card].tx_forward_nsamps = 175;
    openair0_cfg[card].tx_delay = 8;
Raymond Knopp's avatar
 
Raymond Knopp committed
2834
#endif
2835
  } else if(frame_parms[0]->N_RB_DL == 50) {
2836
    sample_rate = 15.36e6;
2837
    bw          = 5.0e6;
2838
#ifndef EXMIMO
2839 2840 2841
    openair0_cfg[card].sample_rate=15.36e6;
    openair0_cfg[card].samples_per_packet = 2048;
    openair0_cfg[card].samples_per_frame = 153600;
2842 2843
    openair0_cfg[card].tx_bw = 5e6;
    openair0_cfg[card].rx_bw = 5e6;
2844 2845
    openair0_cfg[card].tx_forward_nsamps = 95;
    openair0_cfg[card].tx_delay = 5;
Raymond Knopp's avatar
 
Raymond Knopp committed
2846
#endif
2847
  } else if (frame_parms[0]->N_RB_DL == 25) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2848
    sample_rate = 7.68e6;
2849
    bw          = 2.5e6;
2850
#ifndef EXMIMO
2851 2852
    openair0_cfg[card].sample_rate=7.68e6;
    openair0_cfg[card].samples_per_frame = 76800;
2853 2854
    openair0_cfg[card].tx_bw = 2.5e6;
    openair0_cfg[card].rx_bw = 2.5e6;
2855
    openair0_cfg[card].samples_per_packet = 1024;
2856
#ifdef OAI_USRP
2857 2858
    openair0_cfg[card].tx_forward_nsamps = 70;
    openair0_cfg[card].tx_delay = 6;
2859
#elif OAI_BLADERF
2860 2861
    openair0_cfg[card].tx_forward_nsamps = 70;
    openair0_cfg[card].tx_delay = 6;
2862
#endif 
Raymond Knopp's avatar
 
Raymond Knopp committed
2863
#endif
2864
  } else if (frame_parms[0]->N_RB_DL == 6) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2865
    sample_rate = 1.92e6;
2866
    bw          = 0.96e6;
Raymond Knopp's avatar
 
Raymond Knopp committed
2867
#ifndef EXMIMO
2868 2869 2870
    openair0_cfg[card].sample_rate=1.92e6;
    openair0_cfg[card].samples_per_packet = 256;
    openair0_cfg[card].samples_per_frame = 19200;
2871 2872
    openair0_cfg[card].tx_bw = 1.5e6;
    openair0_cfg[card].rx_bw = 1.5e6;
2873 2874
    openair0_cfg[card].tx_forward_nsamps = 40;
    openair0_cfg[card].tx_delay = 8;
Raymond Knopp's avatar
 
Raymond Knopp committed
2875 2876
#endif
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
2877 2878

#ifdef ETHERNET
2879

2880 2881 2882 2883
//calib needed
  openair0_cfg[card].tx_delay = 0;
  openair0_cfg[card].tx_forward_nsamps = 0;

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

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

2890

2891
  for (card=0; card<MAX_CARDS; card++) {
2892
#ifndef EXMIMO
2893
    openair0_cfg[card].samples_per_packet = openair0_cfg[0].samples_per_packet;
2894 2895
#endif
    printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card,
2896 2897
           ((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
2898 2899
    openair0_cfg[card].Mod_id = 0;
#ifdef ETHERNET
2900 2901

    if (UE_flag) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2902
      printf("ETHERNET: Configuring UE ETH for %s:%d\n",rrh_UE_ip,rrh_UE_port);
2903 2904
      openair0_cfg[card].remote_ip   = &rrh_UE_ip[0];
      openair0_cfg[card].remote_port = rrh_UE_port;
2905 2906
    } else {
      printf("ETHERNET: Configuring eNB ETH for %s:%d\n",rrh_eNB_ip,rrh_eNB_port);
2907 2908
      openair0_cfg[card].remote_ip   = &rrh_eNB_ip[0];
      openair0_cfg[card].remote_port = rrh_eNB_port;
ghaddab's avatar
ghaddab committed
2909
    }
2910
openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL;
Raymond Knopp's avatar
 
Raymond Knopp committed
2911
#endif
2912 2913 2914
    openair0_cfg[card].sample_rate = sample_rate;
    openair0_cfg[card].tx_bw = bw;
    openair0_cfg[card].rx_bw = bw;
2915
    // in the case of the USRP, the following variables need to be initialized before the init
2916
    // since the USRP only supports one CC (for the moment), we initialize all the cards with first CC.
2917
    // in the case of EXMIMO2, these values are overwirtten in the function setup_eNB/UE_buffer
2918
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
2919 2920
    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));
2921 2922

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

2924 2925 2926 2927 2928 2929 2930 2931
      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]);
      
2932
      openair0_cfg[card].autocal[i] = 1;
2933
      openair0_cfg[card].tx_gain[i] = tx_gain[0][i];
2934 2935 2936 2937 2938 2939
      if (UE_flag == 0) {
	openair0_cfg[card].rx_gain[i] = PHY_vars_eNB_g[0][0]->rx_total_gain_eNB_dB;
      }
      else {
	openair0_cfg[card].rx_gain[i] = PHY_vars_UE_g[0][0]->rx_total_gain_dB;// - USRP_GAIN_OFFSET;  // calibrated for USRP B210 @ 2.6 GHz, 30.72 MS/s
      }
2940

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

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

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

2954
      default:
2955
        break;
2956
      }
2957 2958


Raymond Knopp's avatar
 
Raymond Knopp committed
2959
    }
2960

2961
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2962
  }
2963

navid's avatar
navid committed
2964 2965 2966
  openair0.func_type = BBU_FUNC;
  openair0_cfg[0].log_level = glog_level;
  
2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980
#ifdef ETHERNET 
  openair0.type=ETH_IF; // not used for the moment
  openair0_dev_init_eth(&openair0, &openair0_cfg[0]);
#else 
#ifdef EXMIMO
  openair0.type=EXMIMO_IF;
  printf("Setting the HW to EXMIMO and initializing openair0 ...\n");
#elif OAI_USRP
  openair0.type=USRP_IF;
  printf("Setting the HW to USRP and initializing openair0 ...\n");
#elif OAI_BLADERF  
  openair0.type=BLADERF_IF;	
  printf("Setting the HW to BLADERF and initializing openair0 ...\n");   
#endif 
navid's avatar
navid committed
2981
 
2982 2983
  if ((mode!=loop_through_memory) && 
      (openair0_device_init(&openair0, &openair0_cfg[0]) <0)) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2984 2985 2986
    printf("Exiting, cannot initialize device\n");
    exit(-1);
  }
2987 2988 2989
  else if (mode==loop_through_memory) {
    
  }
2990
#endif 
2991

2992
  printf("Done\n");
2993 2994 2995

  mac_xface = malloc(sizeof(MAC_xface));

2996
#ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
2997
  int eMBMS_active=0;
2998

Raymond Knopp's avatar
 
Raymond Knopp committed
2999
  l2_init(frame_parms[0],eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL,
3000 3001 3002 3003
          0,// cba_group_active
          0); // HO flag


3004 3005
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3006
  mac_xface->macphy_exit = &exit_fun;
3007

winckel's avatar
winckel committed
3008
#if defined(ENABLE_ITTI)
3009

Raymond Knopp's avatar
 
Raymond Knopp committed
3010
  if (create_tasks(UE_flag ? 0 : 1, UE_flag ? 1 : 0) < 0) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3011
    printf("cannot create ITTI tasks\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3012 3013
    exit(-1); // need a softer mode
  }
3014

Raymond Knopp's avatar
 
Raymond Knopp committed
3015
  printf("ITTI tasks created\n");
winckel's avatar
winckel committed
3016
#endif
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3017 3018

#ifdef OPENAIR2
3019
  if (UE_flag==1) {
3020
    printf("Filling UE band info\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3021
    fill_ue_band_info();
3022
    mac_xface->dl_phy_sync_success (0, 0, 0, 1);
3023
  } else
3024
    mac_xface->mrbch_phy_sync_failure (0, 0, 0);
3025

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3026
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3027

3028
  /* #ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
3029 3030 3031 3032 3033 3034
  //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
3035 3036 3037 3038 3039 3040
  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
3041 3042 3043
  }
  init_predef_traffic(UE_flag ? 1 : 0, UE_flag ? 0 : 1);
  //  }
3044
  #endif */
Raymond Knopp's avatar
 
Raymond Knopp committed
3045

3046
#ifdef EXMIMO
3047
  number_of_cards = openair0_num_detected_cards;
3048 3049
#else
  number_of_cards = 1;
3050
#endif
3051

3052

3053

3054
  for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3055
    rf_map[CC_id].card=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3056
    rf_map[CC_id].chain=CC_id;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3057
  }
3058

Raymond Knopp's avatar
 
Raymond Knopp committed
3059 3060
  // connect the TX/RX buffers
  if (UE_flag==1) {
3061 3062 3063
#ifdef OAI_USRP
    openair_daq_vars.timing_advance = 160;
#else
3064
    openair_daq_vars.timing_advance = 160;
3065
#endif
3066
    if (setup_ue_buffers(UE,&openair0_cfg[0],rf_map)!=0) {
3067 3068 3069
      printf("Error setting up eNB buffer\n");
      exit(-1);
    }
3070

3071
    printf("Setting UE buffer to all-RX\n");
3072

3073
    // Set LSBs for antenna switch (ExpressMIMO)
3074
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3075
      for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++)
3076 3077
        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
3078
    }
3079

3080 3081 3082 3083 3084 3085 3086
    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
3087
    //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX;
3088
  } else {
3089
    openair_daq_vars.timing_advance = 0;
3090

3091 3092 3093 3094
    if (setup_eNB_buffers(PHY_vars_eNB_g[0],&openair0_cfg[0],rf_map)!=0) {
      printf("Error setting up eNB buffer\n");
      exit(-1);
    }
3095

3096
    printf("Setting eNB buffer to all-RX\n");
3097

3098
    // Set LSBs for antenna switch (ExpressMIMO)
3099
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3100
      for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++)
3101 3102
        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
3103
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3104
  }
3105

3106
#ifdef EXMIMO
3107
  openair0_config(&openair0_cfg[0],UE_flag);
Raymond Knopp's avatar
 
Raymond Knopp committed
3108 3109
#endif

3110
  /*
Raymond Knopp's avatar
 
Raymond Knopp committed
3111 3112
      for (ant=0;ant<4;ant++)
      p_exmimo_config->rf.do_autocal[ant] = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3113
  */
3114 3115

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3118 3119 3120 3121 3122 3123
  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);
3124
  else
Raymond Knopp's avatar
 
Raymond Knopp committed
3125
    printf("[OPENAIR][SCHED][INIT] Problem creating EMOS FIFO %d, error_code %d\n",CHANSOUNDER_FIFO_MINOR,error_code);
3126

3127 3128
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3129
  mlockall(MCL_CURRENT | MCL_FUTURE);
3130 3131

#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3132
  // make main thread LXRT soft realtime
3133
  /* task = */ rt_task_init_schmod(nam2num("MAIN"), 9, 0, 0, SCHED_FIFO, 0xF);
Raymond Knopp's avatar
 
Raymond Knopp committed
3134 3135 3136 3137 3138

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3141 3142
  pthread_cond_init(&sync_cond,NULL);
  pthread_mutex_init(&sync_mutex, NULL);
3143

3144
#if defined(ENABLE_ITTI)
3145

Florian Kaltenberger's avatar
Florian Kaltenberger committed
3146 3147 3148 3149 3150
  // Wait for eNB application initialization to be complete (eNB registration to MME)
  if (UE_flag==0) {
    printf("Waiting for eNB application to be ready\n");
    wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB);
  }
3151

3152
#endif
3153

Raymond Knopp's avatar
 
Raymond Knopp committed
3154 3155

  // this starts the DMA transfers
3156
#ifdef EXMIMO
3157

Raymond Knopp's avatar
 
Raymond Knopp committed
3158
  if (UE_flag!=1)
3159
    for (card=0; card<openair0_num_detected_cards; card++)
3160
      openair0_start_rt_acquisition(card);
3161

Raymond Knopp's avatar
 
Raymond Knopp committed
3162
#endif
3163 3164

#ifdef XFORMS
3165 3166
  int UE_id;

Raymond Knopp's avatar
 
Raymond Knopp committed
3167 3168
  if (do_forms==1) {
    fl_initialize (&argc, argv, NULL, 0, 0);
3169 3170

    if (UE_flag==0) {
3171
      form_stats_l2 = create_form_stats_form();
3172 3173 3174
      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");
3175 3176

      for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189
	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");
	  }
	}
3190
      }
3191
    } else {
3192 3193 3194 3195 3196 3197 3198
      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
3199
      if (openair_daq_vars.use_ia_receiver) {
3200 3201 3202 3203 3204
        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
3205 3206 3207
      }
    }

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

3210 3211
    if (ret == 0)
      pthread_setname_np( forms_thread, "xforms" );
3212

Raymond Knopp's avatar
 
Raymond Knopp committed
3213 3214
    printf("Scope thread created, ret=%d\n",ret);
  }
3215

3216 3217 3218
#endif

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3219 3220
  ret = pthread_create(&thread3, NULL, emos_thread, NULL);
  printf("EMOS thread created, ret=%d\n",ret);
jiangx's avatar
jiangx committed
3221 3222
  ret = pthread_create(&thread4, NULL, gps_thread, NULL);
  printf("GPS thread created, ret=%d\n",ret);
3223 3224
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3225
  rt_sleep_ns(10*FRAME_PERIOD);
3226 3227

#ifndef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3228
  pthread_attr_init (&attr_dlsch_threads);
3229
  pthread_attr_setstacksize(&attr_dlsch_threads,4*PTHREAD_STACK_MIN);
3230

3231
  pthread_attr_init (&attr_UE_thread);
3232
  pthread_attr_setstacksize(&attr_UE_thread,8192);//5*PTHREAD_STACK_MIN);
3233

3234
#ifndef LOWLATENCY
3235 3236
  sched_param_UE_thread.sched_priority = sched_get_priority_max(SCHED_FIFO);
  pthread_attr_setschedparam(&attr_UE_thread,&sched_param_UE_thread);
3237
  sched_param_dlsch.sched_priority = sched_get_priority_max(SCHED_FIFO); //OPENAIR_THREAD_PRIORITY;
Raymond Knopp's avatar
 
Raymond Knopp committed
3238 3239
  pthread_attr_setschedparam  (&attr_dlsch_threads, &sched_param_dlsch);
  pthread_attr_setschedpolicy (&attr_dlsch_threads, SCHED_FIFO);
3240
  printf("Setting eNB_thread FIFO scheduling policy with priority %d \n", sched_param_dlsch.sched_priority);
3241
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3242

3243 3244
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3245 3246
  // start the main thread
  if (UE_flag == 1) {
3247
    printf("Intializing UE Threads ...\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3248
    init_UE_threads();
3249 3250 3251 3252 3253
#ifdef DLSCH_THREAD
    init_rx_pdsch_thread();
    rt_sleep_ns(FRAME_PERIOD/10);
    init_dlsch_threads();
#endif
3254

3255
    sleep(1);
3256
#ifdef RTAI
3257
    main_ue_thread = rt_thread_create(UE_thread, NULL, 100000000);
3258
#else
3259
    error_code = pthread_create(&main_ue_thread, &attr_UE_thread, UE_thread, NULL);
3260

Raymond Knopp's avatar
 
Raymond Knopp committed
3261 3262 3263
    if (error_code!= 0) {
      LOG_D(HW,"[lte-softmodem.c] Could not allocate UE_thread, error %d\n",error_code);
      return(error_code);
3264
    } else {
3265 3266
      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
3267
    }
3268

3269
#endif
3270
    printf("UE threads created\n");
3271
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
3272 3273
    if (multi_thread>0) {
      init_eNB_proc();
3274
      sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3275 3276
      LOG_D(HW,"[lte-softmodem.c] eNB threads created\n");
    }
3277

3278
    printf("Creating main eNB_thread \n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3279
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3280
    main_eNB_thread = rt_thread_create(eNB_thread, NULL, PTHREAD_STACK_MIN);
Raymond Knopp's avatar
 
Raymond Knopp committed
3281
#else
3282
    error_code = pthread_create( &main_eNB_thread, &attr_dlsch_threads, eNB_thread, NULL );
3283

Raymond Knopp's avatar
 
Raymond Knopp committed
3284 3285 3286
    if (error_code!= 0) {
      LOG_D(HW,"[lte-softmodem.c] Could not allocate eNB_thread, error %d\n",error_code);
      return(error_code);
3287
    } else {
3288 3289
      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
3290
    }
3291

Raymond Knopp's avatar
 
Raymond Knopp committed
3292 3293
#endif
  }
3294

Raymond Knopp's avatar
 
Raymond Knopp committed
3295
  // Sleep to allow all threads to setup
Raymond Knopp's avatar
 
Raymond Knopp committed
3296
  sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3297

3298
#ifdef USE_MME
3299

3300 3301 3302
  while (start_UE == 0) {
    sleep(1);
  }
3303

3304 3305
#endif

3306
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3307
#ifndef USRP_DEBUG
3308
  if (mode!=loop_through_memory)
navid's avatar
navid committed
3309 3310 3311
    if (openair0.trx_start_func(&openair0) != 0 ) 
      LOG_E(HW,"Could not start the device\n");

Raymond Knopp's avatar
 
Raymond Knopp committed
3312
#endif
3313 3314
#endif

3315

Raymond Knopp's avatar
 
Raymond Knopp committed
3316
  pthread_mutex_lock(&sync_mutex);
3317
  sync_var=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3318 3319
  pthread_cond_broadcast(&sync_cond);
  pthread_mutex_unlock(&sync_mutex);
3320

Raymond Knopp's avatar
 
Raymond Knopp committed
3321 3322 3323
  // wait for end of program
  printf("TYPE <CTRL-C> TO TERMINATE\n");
  //getchar();
3324 3325

#if defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
3326 3327
  printf("Entering ITTI signals handler\n");
  itti_wait_tasks_end();
3328
  oai_exit=1;
3329
#else
3330

Raymond Knopp's avatar
 
Raymond Knopp committed
3331 3332
  while (oai_exit==0)
    rt_sleep_ns(FRAME_PERIOD);
3333

3334
#endif
3335

Raymond Knopp's avatar
 
Raymond Knopp committed
3336
  // stop threads
3337
#ifdef XFORMS
Raymond Knopp's avatar
 
Raymond Knopp committed
3338
  printf("waiting for XFORMS thread\n");
3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352

  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++) {
3353 3354 3355 3356
	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
3357
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
3358
    }
3359 3360
  }

3361 3362
#endif

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3365 3366
  // cleanup
  if (UE_flag == 1) {
3367
#ifdef EXMIMO
3368
#ifdef RTAI
3369
    rt_thread_join(main_ue_thread);
3370
#else
3371
    pthread_join(main_ue_thread,&status);
3372 3373
#endif
#ifdef DLSCH_THREAD
Raymond Knopp's avatar
 
Raymond Knopp committed
3374 3375
    cleanup_dlsch_threads();
    cleanup_rx_pdsch_thread();
3376
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3377
#endif
3378
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
3379
#ifdef DEBUG_THREADS
Raymond Knopp's avatar
 
Raymond Knopp committed
3380
    printf("Joining eNB_thread ...");
Raymond Knopp's avatar
 
Raymond Knopp committed
3381
#endif
3382
#ifdef RTAI
3383
    rt_thread_join(main_eNB_thread);
3384
#else
3385 3386
    int *eNB_thread_status_p;
    int result = pthread_join( main_eNB_thread, (void**)&eNB_thread_status_p );
Raymond Knopp's avatar
 
Raymond Knopp committed
3387
#ifdef DEBUG_THREADS
3388

3389
    if (result != 0) {
3390
      printf( "\nError joining main_eNB_thread.\n" );
3391
    } else {
3392 3393 3394 3395 3396
      if (eNB_thread_status_p) {
        printf( "status %d\n", *eNB_thread_status_p );
      } else {
        printf( "The thread was killed. No status available.\n");
      }
3397
    }
3398

3399 3400
#else
    UNUSED(result);
3401 3402
#endif // DEBUG_THREADS
#endif // RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3403

Raymond Knopp's avatar
 
Raymond Knopp committed
3404 3405 3406
    if (multi_thread>0) {
      printf("Killing eNB processing threads\n");
      kill_eNB_proc();
Raymond Knopp's avatar
 
Raymond Knopp committed
3407

Raymond Knopp's avatar
 
Raymond Knopp committed
3408
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3409
  }
3410

3411
#ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
3412
  //cleanup_pdcp_thread();
3413 3414
#endif

3415
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3416
  stop_rt_timer();
3417
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3418 3419
  pthread_cond_destroy(&sync_cond);
  pthread_mutex_destroy(&sync_mutex);
3420

3421

3422
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3423
  printf("stopping card\n");
3424
  openair0_stop(0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3425 3426
  printf("closing openair0_lib\n");
  openair0_close();
Raymond Knopp's avatar
 
Raymond Knopp committed
3427
#endif
3428 3429

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3430 3431 3432
  printf("waiting for EMOS thread\n");
  pthread_cancel(thread3);
  pthread_join(thread3,&status);
jiangx's avatar
jiangx committed
3433 3434 3435
  printf("waiting for GPS thread\n");
  pthread_cancel(thread4);
  pthread_join(thread4,&status);
3436 3437 3438
#endif

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3439 3440
  error_code = rtf_destroy(CHANSOUNDER_FIFO_MINOR);
  printf("[OPENAIR][SCHED][CLEANUP] EMOS FIFO closed, error_code %d\n", error_code);
3441 3442
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3443
  if (ouput_vcd)
3444
    VCD_SIGNAL_DUMPER_CLOSE();
3445

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3446
#ifdef OPENAIR2
3447

3448
  if (opt_enabled == 1)
3449
    terminate_opt();
3450

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3451
#endif
3452

Raymond Knopp's avatar
 
Raymond Knopp committed
3453
  logClean();
3454

Raymond Knopp's avatar
 
Raymond Knopp committed
3455 3456
  return 0;
}
3457 3458


3459 3460 3461
/* 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
3462
   antennas are mapped to successive RF chains on the same card. */
3463 3464
int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs])
{
3465

3466
  int i, CC_id;
3467
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3468
  uint16_t N_TA_offset = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3469 3470
#else
  int j;
Raymond Knopp's avatar
 
Raymond Knopp committed
3471
#endif
3472
  LTE_DL_FRAME_PARMS *frame_parms;
3473

Raymond Knopp's avatar
 
Raymond Knopp committed
3474

3475 3476
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    if (phy_vars_eNB[CC_id]) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3477 3478
      frame_parms = &(phy_vars_eNB[CC_id]->lte_frame_parms);
      printf("setup_eNB_buffers: frame_parms = %p\n",frame_parms);
3479
    } else {
3480 3481
      printf("phy_vars_eNB[%d] not initialized\n", CC_id);
      return(-1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3482
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3483

3484
#ifndef EXMIMO
3485

3486 3487
    if (frame_parms->frame_type == TDD) {
      if (frame_parms->N_RB_DL == 100)
3488
        N_TA_offset = 624;
3489
      else if (frame_parms->N_RB_DL == 50)
3490
        N_TA_offset = 624/2;
3491
      else if (frame_parms->N_RB_DL == 25)
3492
        N_TA_offset = 624/4;
Raymond Knopp's avatar
 
Raymond Knopp committed
3493
    }
3494

Raymond Knopp's avatar
 
Raymond Knopp committed
3495
#endif
3496 3497


3498 3499 3500



Raymond Knopp's avatar
 
Raymond Knopp committed
3501
    // replace RX signal buffers with mmaped HW versions
3502
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3503 3504 3505
    openair0_cfg[CC_id].tx_num_channels = 0;
    openair0_cfg[CC_id].rx_num_channels = 0;

3506
    for (i=0; i<frame_parms->nb_antennas_rx; i++) {
3507 3508 3509
      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];
3510

3511
      if (openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i]) {
3512 3513 3514 3515 3516 3517
        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++;
3518
      }
3519

3520
      printf("rxdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]);
3521 3522 3523 3524

      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;
3525
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
3526
    }
3527 3528

    for (i=0; i<frame_parms->nb_antennas_tx; i++) {
3529 3530 3531
      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];
3532

3533
      if (openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i]) {
3534 3535 3536 3537 3538 3539
        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++;
3540
      }
3541

3542
      printf("txdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3543 3544 3545 3546

      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;
3547
      }
3548
    }
3549

3550
#else // not EXMIMO
3551 3552 3553
    rxdata = (int32_t**)malloc16(frame_parms->nb_antennas_rx*sizeof(int32_t*));
    txdata = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*));

3554
    for (i=0; i<frame_parms->nb_antennas_rx; i++) {
3555
      free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]);
3556
      rxdata[i] = (int32_t*)(16 + malloc16(16+openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation
3557
      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
3558
      memset(rxdata[i], 0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t));
3559
      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);
3560
      
Raymond Knopp's avatar
 
Raymond Knopp committed
3561
    }
3562 3563

    for (i=0; i<frame_parms->nb_antennas_tx; i++) {
3564
      free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3565
      txdata[i] = (int32_t*)(16 + malloc16(16 + openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation
3566
      phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i] = txdata[i];
3567
      memset(txdata[i],0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t));
3568
      printf("txdata[%d] @ %p\n", i, phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3569

Raymond Knopp's avatar
 
Raymond Knopp committed
3570
    }
3571

Raymond Knopp's avatar
 
Raymond Knopp committed
3572
#endif
3573
  }
3574

3575
  return(0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3576
}
3577

3578
void reset_opp_meas(void) {
3579 3580 3581
  int sfn;
  reset_meas(&softmodem_stats_mt);
  reset_meas(&softmodem_stats_hw);
3582
  
3583 3584 3585 3586 3587 3588
  for (sfn=0; sfn < 10; sfn++) {
    reset_meas(&softmodem_stats_tx_sf[sfn]);
    reset_meas(&softmodem_stats_rx_sf[sfn]);
  }
}

3589 3590
void print_opp_meas(void) {

3591 3592 3593
  int sfn=0;
  print_meas(&softmodem_stats_mt, "Main ENB Thread", NULL, NULL);
  print_meas(&softmodem_stats_hw, "HW Acquisation", NULL, NULL);
3594
  
3595 3596 3597 3598 3599
  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);
  }
}
3600 3601