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

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


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

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

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

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

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

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

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

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

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

#include "PHY/types.h"
66

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

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

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

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

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

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

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

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

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

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

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

#define FRAME_PERIOD    100000000ULL
#define DAQ_PERIOD      66667ULL

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

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

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


Raymond Knopp's avatar
 
Raymond Knopp committed
147

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

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

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

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

#ifdef RTAI
171

172 173
static long                      main_eNB_thread;
static long                      main_ue_thread;
174

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

179
pthread_attr_t                  attr_dlsch_threads;
180 181
pthread_attr_t                  attr_UE_thread;

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

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

191

192 193


194
struct sched_param              sched_param_UE_thread;
195

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
212

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

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

223

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
234

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

238
static char                     threequarter_fs=0;
239

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

243
openair0_rf_map rf_map[MAX_NUM_CCs];
244

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

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

254 255
FILE *input_fd=NULL;

256

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

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

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

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

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

#endif
300 301

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
324

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
361 362

#ifdef ETHERNET
363 364
char *rrh_UE_ip = "127.0.0.1";
int rrh_UE_port = 51000;
Raymond Knopp's avatar
 
Raymond Knopp committed
365
#endif
366 367 368 369 370 371

/* flag set by eNB conf file to specify if the radio head is local or remote (default option is local) */
uint8_t local_remote_radio = BBU_LOCAL_RADIO_HEAD;
/* struct for ethernet specific parameters given in eNB conf file */
eth_params_t *eth_params;

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

376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416
/*---------------------BMC: timespec helpers -----------------------------*/

struct timespec min_diff_time = { .tv_sec = 0, .tv_nsec = 0 };
struct timespec max_diff_time = { .tv_sec = 0, .tv_nsec = 0 };

struct timespec clock_difftime(struct timespec start, struct timespec end)
{
    struct timespec temp;
    if ((end.tv_nsec-start.tv_nsec)<0) {
        temp.tv_sec = end.tv_sec-start.tv_sec-1;
	temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
    } else {
        temp.tv_sec = end.tv_sec-start.tv_sec;
	temp.tv_nsec = end.tv_nsec-start.tv_nsec;
    }
    return temp;
}

void print_difftimes()
{
#ifdef DEBUG
    printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
#else
    LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
#endif
}

void update_difftimes(struct timespec start, struct timespec end)
{
    struct timespec diff_time = { .tv_sec = 0, .tv_nsec = 0 };
    int             changed = 0;
    diff_time = clock_difftime(start, end);
    if ((min_diff_time.tv_nsec == 0) || (diff_time.tv_nsec < min_diff_time.tv_nsec)) { min_diff_time.tv_nsec = diff_time.tv_nsec; changed = 1; }
    if ((max_diff_time.tv_nsec == 0) || (diff_time.tv_nsec > max_diff_time.tv_nsec)) { max_diff_time.tv_nsec = diff_time.tv_nsec; changed = 1; }
#if 1
    if (changed) print_difftimes();
#endif
}

/*------------------------------------------------------------------------*/

417
unsigned int build_rflocal(int txi, int txq, int rxi, int rxq)
418
{
Raymond Knopp's avatar
 
Raymond Knopp committed
419
  return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
420 421 422
}
unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
423
  return (dcoff_i_rxfe + (dcoff_q_rxfe<<8));
424 425
}

426
#if !defined(ENABLE_ITTI)
427 428 429 430 431 432 433 434
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);
435

436 437 438 439
    // print out all the frames to stderr
    fprintf(stderr, "Error: signal %d:\n", sig);
    backtrace_symbols_fd(array, size, 2);
    exit(-1);
440 441
  } else {
    printf("trying to exit gracefully...\n");
442
    oai_exit = 1;
443 444
  }
}
445
#endif
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
#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
461 462
  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");
463
  printf("  --no-L2-connect bypass L2 and upper layers\n");
464 465 466 467
  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");
468
  printf("  -C Set the downlink frequency for all component carriers\n");
469 470 471 472 473 474 475 476 477
  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("  -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
478
  printf("  -r Set the PRB, valid values: 6, 25, 50, 100  \n");    
479 480
  printf("  -S Skip the missed slots/subframes \n");    
  printf("  -t Set the maximum uplink MCS\n");
481
  printf("  -T Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n");
482 483 484 485
  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);    
486

487
}
488 489
void exit_fun(const char* s)
{
490
  if (s != NULL) {
491
    printf("%s %s() Exiting OAI softmodem: %s\n",__FILE__, __FUNCTION__, s);
492 493 494 495 496
  }

  oai_exit = 1;

#if defined(ENABLE_ITTI)
Florian Kaltenberger's avatar
Florian Kaltenberger committed
497
  sleep(1); //allow lte-softmodem threads to exit first
498
  itti_terminate_tasks (TASK_UNKNOWN);
499
#endif
500 501 502 503 504 505

  //rt_sleep_ns(FRAME_PERIOD);

  //exit (-1);
}

506

507
#ifdef XFORMS
508

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

  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    for (k=0; k<8; k++) { //harq_processes
      for (j=0; j<phy_vars_eNB->dlsch_eNB[i][0]->Mdlharq; j++) {
        phy_vars_eNB->eNB_UE_stats[i].dlsch_NAK[k][j]=0;
        phy_vars_eNB->eNB_UE_stats[i].dlsch_ACK[k][j]=0;
        phy_vars_eNB->eNB_UE_stats[i].dlsch_trials[k][j]=0;
520
      }
521

522 523 524
      phy_vars_eNB->eNB_UE_stats[i].dlsch_l2_errors[k]=0;
      phy_vars_eNB->eNB_UE_stats[i].ulsch_errors[k]=0;
      phy_vars_eNB->eNB_UE_stats[i].ulsch_consecutive_errors=0;
525 526 527 528 529 530

      for (j=0; j<phy_vars_eNB->ulsch_eNB[i]->Mdlharq; j++) {
        phy_vars_eNB->eNB_UE_stats[i].ulsch_decoding_attempts[k][j]=0;
        phy_vars_eNB->eNB_UE_stats[i].ulsch_decoding_attempts_last[k][j]=0;
        phy_vars_eNB->eNB_UE_stats[i].ulsch_round_errors[k][j]=0;
        phy_vars_eNB->eNB_UE_stats[i].ulsch_round_fer[k][j]=0;
531
      }
532
    }
533

534 535 536
    phy_vars_eNB->eNB_UE_stats[i].dlsch_sliding_cnt=0;
    phy_vars_eNB->eNB_UE_stats[i].dlsch_NAK_round0=0;
    phy_vars_eNB->eNB_UE_stats[i].dlsch_mcs_offset=0;
537 538 539
  }
}

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

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

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

555
# ifdef ENABLE_XFORMS_WRITE_STATS
556 557

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

562
#endif
563

Raymond Knopp's avatar
 
Raymond Knopp committed
564 565
  while (!oai_exit) {
    if (UE_flag==1) {
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
566
      len = dump_ue_stats (PHY_vars_UE_g[0][0], stats_buffer, 0, mode,rx_input_level_dBm);
knopp's avatar
knopp committed
567 568 569
      //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);
570

571 572 573 574 575
      phy_scope_UE(form_ue[0],
                   PHY_vars_UE_g[0][0],
                   0,
                   0,7);

Raymond Knopp's avatar
 
Raymond Knopp committed
576
    } else {
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
577 578
#ifdef OPENAIR2
      len = dump_eNB_l2_stats (stats_buffer, 0);
knopp's avatar
knopp committed
579 580 581
      //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
582 583
#endif
      len = dump_eNB_stats (PHY_vars_eNB_g[0][0], stats_buffer, 0);
584

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

588 589 590
      //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);
591

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

600
    }
601

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

607
  //  printf("%s",stats_buffer);
608

609
# ifdef ENABLE_XFORMS_WRITE_STATS
610

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

625
# endif
626

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

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

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

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

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

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

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

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

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

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

674 675 676

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

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

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

  pthread_exit((void*) arg);

}

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

jiangx's avatar
jiangx committed
716
  int channel_buffer_size,ret;
717

718 719 720
  time_t timer;
  struct tm *now;

721
  struct sched_param sched_param;
722 723

  sched_param.sched_priority = sched_get_priority_max(SCHED_FIFO)-1;
724
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
725

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

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

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

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


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

  dumpfile_id = fopen(dumpfile_name,"w");
758 759 760 761 762

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


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

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

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

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

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

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

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

820 821 822
  free(fifo2file_buffer);
  fclose(dumpfile_id);
  close(fifo);
823

824 825 826 827 828
  pthread_exit((void*) arg);

}
#endif

829 830


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

    while ((!oai_exit) && (*start_flag == 0)) {
      LOG_N(EMU, message, indicator[i]);
843
      fflush(stdout);
844 845 846
      i = (i + 1) % (sizeof(indicator) / sizeof(indicator[0]));
      usleep(200000);
    }
847

848 849 850 851 852
    LOG_D(EMU,"\n");
  }
}
#endif

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

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
861

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

871 872 873
      itti_receive_msg (TASK_L2L1, &message_p);

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

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

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
927
  return NULL;
928 929 930
}
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
931

932 933
void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
934 935 936 937

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

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
950

Raymond Knopp's avatar
 
Raymond Knopp committed
951
    for (aa=0; aa<phy_vars_eNB->lte_frame_parms.nb_antennas_tx; aa++) {
952 953 954
      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,
955
                     phy_vars_eNB->lte_frame_parms.ofdm_symbol_size,
956 957 958 959 960
                     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),
961
                     phy_vars_eNB->lte_frame_parms.ofdm_symbol_size,
962 963 964 965 966 967 968 969
                     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));
970 971 972 973 974 975
	// 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
976
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
977

978 979 980 981 982 983 984
      // 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++) {
985 986 987 988 989 990 991 992
        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;

993 994 995 996
	((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[0] = ((short*)dummy_tx_b)[2*i]<<openair0_cfg[0].iq_txshift;
	
	((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[1] = ((short*)dummy_tx_b)[2*i+1]<<openair0_cfg[0].iq_txshift;
  
997 998 999 1000 1001 1002 1003
     }
     // 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;
       }
     }
1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022

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

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

1037 1038 1039 1040 1041 1042 1043 1044 1045
/*!
 * \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
1046 1047

  eNB_proc_t *proc = (eNB_proc_t*)param;
1048 1049
  FILE  *tx_time_file;
  char tx_time_name[101];
kaltenbe's avatar
kaltenbe committed
1050

1051 1052 1053 1054
  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");
  }
1055 1056 1057
  // set default return value
  eNB_thread_tx_status[proc->subframe] = 0;

1058 1059
  MSC_START_USE();

Raymond Knopp's avatar
 
Raymond Knopp committed
1060 1061
#ifdef RTAI
  RT_TASK *task;
1062
  char task_name[8];
Raymond Knopp's avatar
 
Raymond Knopp committed
1063

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1077
#else
1078
#ifdef LOWLATENCY
1079 1080
  struct sched_attr attr;
  unsigned int flags = 0;
navid's avatar
navid committed
1081 1082 1083 1084 1085 1086 1087
  uint64_t runtime  = (uint64_t) (get_runtime_tx(proc->subframe, runtime_phy_tx, target_dl_mcs,frame_parms[0]->N_RB_DL,cpuf,PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx) *  1000000); 
  uint64_t deadline = 1   *  1000000; // each tx thread will finish within 1ms
  uint64_t period   = 1   * 10000000; // each tx thread has a period of 10ms from the starting point
  if (runtime > 1000000 ){
    LOG_W(HW,"estimated runtime %d is larger than 1ms, adjusting\n",runtime);
    runtime = (0.97 * 100) * 10000; 
  }
1088

1089 1090 1091 1092
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1093

navid's avatar
navid committed
1094 1095 1096 1097
  attr.sched_policy   = SCHED_DEADLINE;
  attr.sched_runtime  = runtime;
  attr.sched_deadline = deadline;
  attr.sched_period   = period; 
1098

1099 1100 1101 1102
  if (sched_setattr(0, &attr, flags) < 0 ) {
    perror("[SCHED] eNB tx thread: sched_setattr failed\n");
    return &eNB_thread_tx_status[proc->subframe];
  }
1103

navid's avatar
navid committed
1104
  LOG_I( HW, "[SCHED] eNB TX deadline thread %d(TID %ld) started on CPU %d\n", proc->subframe, gettid(), sched_getcpu() );
1105
#else
1106
  LOG_I( HW, "[SCHED][eNB] TX thread %d started on CPU %d TID %d\n", proc->subframe, sched_getcpu(),gettid() );
1107 1108
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
1109 1110 1111 1112 1113 1114 1115 1116
#endif

  mlockall(MCL_CURRENT | MCL_FUTURE);

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

1117
  while (!oai_exit) {
1118

1119
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe), 0 );
1120

1121
    if (pthread_mutex_lock(&proc->mutex_tx) != 0) {
1122
      LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc %d\n", proc->subframe );
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1123
      exit_fun("nothing to add");
1124
      break;
1125
    }
1126

1127
    while (proc->instance_cnt_tx < 0) {
1128 1129 1130
      // 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
1131
    }
1132

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

1139 1140
    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 );
1141 1142 1143
    start_meas( &softmodem_stats_tx_sf[proc->subframe] );

    if (oai_exit) break;
1144

1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156
    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;
      }
1157 1158
      /* wait for our turn or oai_exit */
      while (sync_phy_proc[proc->subframe].phy_proc_CC_id != proc->CC_id && !oai_exit) {
1159 1160 1161
        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
1162

1163 1164 1165
      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");
1166 1167
      }

1168 1169 1170
      if (oai_exit)
        break;

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

1173
      /* we're done, let the next one proceed */
1174 1175 1176 1177 1178
      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;
      }
1179 1180 1181 1182
      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) {
1183
        LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc %d\n", proc->subframe);
1184 1185 1186
        exit_fun("nothing to add");
        break;
      }
1187
    }
1188

1189
    do_OFDM_mod_rt( proc->subframe_tx, PHY_vars_eNB_g[0][proc->CC_id] );
kaltenbe's avatar
kaltenbe committed
1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203
    /*
    short *txdata = (short*)&PHY_vars_eNB_g[0][proc->CC_id]->lte_eNB_common_vars.txdata[0][0][proc->subframe_tx*PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.samples_per_tti];
    int i;
    for (i=0;i<7680*2;i+=8) {
      txdata[i] = 2047;
      txdata[i+1] = 0;
      txdata[i+2] = 0;
      txdata[i+3] = 2047;
      txdata[i+4] = -2047;
      txdata[i+5] = 0;
      txdata[i+6] = 0;
      txdata[i+7] = -2047;
    }
    */
1204 1205 1206 1207 1208
    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
1209

1210 1211 1212 1213 1214 1215 1216 1217 1218
    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++;
1219

1220 1221
    if (proc->frame_tx==1024)
      proc->frame_tx=0;
1222
    stop_meas( &softmodem_stats_tx_sf[proc->subframe] );
1223 1224 1225 1226 1227 1228 1229
#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 
1230 1231
    print_meas_now(&softmodem_stats_tx_sf[proc->subframe],"eNB_TX_SF",proc->subframe, tx_time_file);

1232 1233
  }

1234 1235


1236
  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
1237

Raymond Knopp's avatar
 
Raymond Knopp committed
1238 1239 1240
#ifdef HARD_RT
  rt_make_soft_real_time();
#endif
1241

Raymond Knopp's avatar
 
Raymond Knopp committed
1242
#ifdef DEBUG_THREADS
1243
  printf( "Exiting eNB thread TX %d\n", proc->subframe );
Raymond Knopp's avatar
 
Raymond Knopp committed
1244 1245 1246 1247 1248
#endif
  // clean task
#ifdef RTAI
  rt_task_delete(task);
#endif
1249

1250 1251
  eNB_thread_tx_status[proc->subframe] = 0;
  return &eNB_thread_tx_status[proc->subframe];
Raymond Knopp's avatar
 
Raymond Knopp committed
1252 1253 1254
}


1255 1256 1257 1258 1259 1260 1261 1262 1263 1264
/*!
 * \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
1265
  eNB_proc_t *proc = (eNB_proc_t*)param;
1266

1267 1268
  FILE  *rx_time_file;
  char rx_time_name[101];
Raymond Knopp's avatar
 
Raymond Knopp committed
1269 1270
  int i;

1271 1272 1273 1274
  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");
  }
1275 1276 1277
  // set default return value
  eNB_thread_rx_status[proc->subframe] = 0;

1278 1279
  MSC_START_USE();

Raymond Knopp's avatar
 
Raymond Knopp committed
1280 1281
#ifdef RTAI
  RT_TASK *task;
1282
  char task_name[8];
Raymond Knopp's avatar
 
Raymond Knopp committed
1283

1284
  sprintf(task_name,"RXC%1dS%1d",proc->CC_id,proc->subframe);
Raymond Knopp's avatar
 
Raymond Knopp committed
1285 1286 1287
  task = rt_task_init_schmod(nam2num(task_name), 0, 0, 0, SCHED_FIFO, 0xF);

  if (task==NULL) {
1288 1289
    LOG_E(PHY,"[SCHED][eNB] Problem starting eNB_proc_RX thread_index %d (%s)!!!!\n",proc->subframe,task_name);
    return 0;
1290
  } else {
1291
    LOG_I(PHY,"[SCHED][eNB] eNB RX thread CC_id %d SF %d started with id %p\n", /*  on CPU %d*/
1292 1293 1294
          proc->CC_id,
          proc->subframe,
          task); /*,rtai_cpuid()*/
Raymond Knopp's avatar
 
Raymond Knopp committed
1295
  }
1296

Raymond Knopp's avatar
 
Raymond Knopp committed
1297
#else
1298
#ifdef LOWLATENCY
1299 1300
  struct sched_attr attr;
  unsigned int flags = 0;
navid's avatar
navid committed
1301 1302 1303 1304 1305 1306 1307 1308
  uint64_t runtime  = get_runtime_rx(proc->subframe, runtime_phy_rx, target_ul_mcs,frame_parms[0]->N_RB_DL,cpuf,PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx)  *  1000000; 
  uint64_t deadline = 1   *  1000000;
  uint64_t period   = 1   * 10000000; // each rx thread has a period of 10ms from the starting point
  if (runtime  > 2300000 ) {
    LOG_W(HW,"estimated rx runtime %d is larger than expected, adjusting\n",runtime);
    runtime   = 2300000;
    deadline  = runtime + 100000;
  }
1309

1310 1311 1312 1313
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1314

1315
  attr.sched_policy = SCHED_DEADLINE;
navid's avatar
navid committed
1316 1317 1318
  attr.sched_runtime  = runtime;
  attr.sched_deadline = deadline;
  attr.sched_period   = period; 
1319 1320

  if (sched_setattr(0, &attr, flags) < 0 ) {
1321
    perror("[SCHED] eNB RX sched_setattr failed\n");
1322
    return &eNB_thread_rx_status[proc->subframe];
1323
  }
1324

1325
  LOG_I( HW, "[SCHED] eNB RX deadline thread %d(TID %ld) started on CPU %d\n", proc->subframe, gettid(), sched_getcpu() );
1326
#else
1327
  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
1328
#endif
1329
#endif // RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
1330 1331 1332 1333 1334 1335 1336

  mlockall(MCL_CURRENT | MCL_FUTURE);

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

1337
  while (!oai_exit) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1338

1339
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 0 );
1340

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

1347
    while (proc->instance_cnt_rx < 0) {
1348 1349 1350
      // 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
1351
    }
1352 1353 1354 1355 1356 1357 1358

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

1359 1360
    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 );
1361
    start_meas( &softmodem_stats_rx_sf[proc->subframe] );
1362

Raymond Knopp's avatar
 
Raymond Knopp committed
1363
    if (oai_exit) break;
1364

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

1368
      phy_procedures_eNB_RX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay );
Raymond Knopp's avatar
 
Raymond Knopp committed
1369
    }
1370 1371

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1375
    if (pthread_mutex_lock(&proc->mutex_rx) != 0) {
1376 1377 1378
      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
1379
    }
1380 1381 1382 1383 1384 1385 1386

    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
1387
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1388 1389

    proc->frame_rx++;
1390

Raymond Knopp's avatar
 
Raymond Knopp committed
1391 1392
    if (proc->frame_rx==1024)
      proc->frame_rx=0;
1393

1394
    stop_meas( &softmodem_stats_rx_sf[proc->subframe] );
1395 1396 1397 1398 1399 1400 1401
#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  
1402
    print_meas_now(&softmodem_stats_rx_sf[proc->subframe],"eNB_RX_SF",proc->subframe, rx_time_file);
Raymond Knopp's avatar
 
Raymond Knopp committed
1403
  }
1404

1405
  //stop_meas( &softmodem_stats_rx_sf[proc->subframe] );
1406
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 0 );
1407

Raymond Knopp's avatar
 
Raymond Knopp committed
1408
#ifdef HARD_RT
Raymond Knopp's avatar
 
Raymond Knopp committed
1409 1410 1411 1412
  rt_make_soft_real_time();
#endif

#ifdef DEBUG_THREADS
1413
  printf( "Exiting eNB thread RX %d\n", proc->subframe );
Raymond Knopp's avatar
 
Raymond Knopp committed
1414 1415 1416 1417
#endif
  // clean task
#ifdef RTAI
  rt_task_delete(task);
Raymond Knopp's avatar
 
Raymond Knopp committed
1418 1419
#endif

1420 1421
  eNB_thread_rx_status[proc->subframe] = 0;
  return &eNB_thread_rx_status[proc->subframe];
Raymond Knopp's avatar
 
Raymond Knopp committed
1422 1423 1424 1425
}



Raymond Knopp's avatar
 
Raymond Knopp committed
1426

1427 1428
void init_eNB_proc(void)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1429
  int i;
Raymond Knopp's avatar
 
Raymond Knopp committed
1430 1431
  int CC_id;

1432 1433 1434
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    for (i=0; i<NUM_ENB_THREADS; i++) {
      // set the stack size
navid's avatar
navid committed
1435
     
1436

navid's avatar
navid committed
1437 1438 1439 1440 1441 1442
#ifndef LOWLATENCY 
      /*  
       pthread_attr_init( &attr_eNB_proc_tx[CC_id][i] );
       if (pthread_attr_setstacksize( &attr_eNB_proc_tx[CC_id][i], 64 *PTHREAD_STACK_MIN ) != 0)
        perror("[ENB_PROC_TX] setting thread stack size failed\n");
      
1443
      pthread_attr_init( &attr_eNB_proc_rx[CC_id][i] );
navid's avatar
navid committed
1444
      if (pthread_attr_setstacksize( &attr_eNB_proc_rx[CC_id][i], 64 * PTHREAD_STACK_MIN ) != 0)
1445
        perror("[ENB_PROC_RX] setting thread stack size failed\n");
1446
      */
1447
      // set the kernel scheduling policy and priority
Raymond Knopp's avatar
 
Raymond Knopp committed
1448 1449 1450 1451 1452 1453
      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);
1454
      printf("Setting OS scheduler to SCHED_FIFO for eNB [cc%d][thread%d] \n",CC_id, i);
1455
#endif
1456 1457 1458
      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
1459
      PHY_vars_eNB_g[0][CC_id]->proc[i].CC_id = CC_id;
1460 1461 1462 1463
      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);
1464 1465 1466 1467
#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 
1468 1469
      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] );
1470
#endif
1471 1472 1473 1474 1475
      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
1476 1477
      PHY_vars_eNB_g[0][CC_id]->proc[i].frame_tx = 0;
      PHY_vars_eNB_g[0][CC_id]->proc[i].frame_rx = 0;
1478
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
1479 1480
      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
1481
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
1482 1483
      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
1484
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1485
    }
1486 1487


1488
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
1489 1490
    // 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
1491

Raymond Knopp's avatar
 
Raymond Knopp committed
1492
    //PHY_vars_eNB_g[0][CC_id]->proc[0].frame_rx = 1023;
Raymond Knopp's avatar
 
Raymond Knopp committed
1493 1494
    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
1495
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
1496 1497
    // 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
1498
    //    PHY_vars_eNB_g[0][CC_id]->proc[7].frame_tx = 1;
Raymond Knopp's avatar
 
Raymond Knopp committed
1499 1500
    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
1501
    //    PHY_vars_eNB_g[0][CC_id]->proc[0].frame_tx = 1;
Raymond Knopp's avatar
 
Raymond Knopp committed
1502
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1503
  }
1504 1505 1506 1507 1508 1509 1510

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

1513 1514 1515 1516 1517 1518
/*!
 * \brief Terminate eNB TX and RX threads.
 */
void kill_eNB_proc(void)
{
  int *status;
Raymond Knopp's avatar
 
Raymond Knopp committed
1519

1520 1521
  for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++)
    for (int i=0; i<NUM_ENB_THREADS; i++) {
1522

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1536
#ifdef DEBUG_THREADS
1537

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1552
#ifdef DEBUG_THREADS
1553
      printf( "Killing RX CC_id %d thread %d\n", CC_id, i );
Raymond Knopp's avatar
 
Raymond Knopp committed
1554
#endif
1555 1556 1557 1558

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

1564 1565
#ifdef DEBUG_THREADS

1566 1567 1568 1569 1570 1571 1572 1573 1574
      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" );
        }
      }
1575

1576 1577
#else
      UNUSED(result)
Raymond Knopp's avatar
 
Raymond Knopp committed
1578
#endif
1579 1580 1581 1582 1583

      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
1584
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1585 1586 1587
}


Raymond Knopp's avatar
 
Raymond Knopp committed
1588 1589


1590

Raymond Knopp's avatar
 
Raymond Knopp committed
1591

1592 1593 1594 1595 1596 1597
/*!
 * \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 )
1598
{
1599 1600
  UNUSED(arg);
  static int eNB_thread_status;
1601

1602
  unsigned char slot;
1603
#ifdef EXMIMO
1604
  slot=0;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1605
  RTIME time_in;
Raymond Knopp's avatar
 
Raymond Knopp committed
1606
  volatile unsigned int *DAQ_MBOX = openair0_daq_cnt();
Raymond Knopp's avatar
 
Raymond Knopp committed
1607 1608
  int mbox_target=0,mbox_current=0;
  int hw_slot,delay_cnt;
Raymond Knopp's avatar
 
Raymond Knopp committed
1609 1610
  int diff;
  int ret;
1611
  int first_run=1;
Raymond Knopp's avatar
 
Raymond Knopp committed
1612
#else
1613 1614 1615
  // the USRP implementation operates on subframes, not slots
  // one subframe consists of one even and one odd slot
  slot = 1;
1616
  int spp;
1617
  int tx_launched = 0;
1618
  int card=0;
1619 1620 1621

  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
1622

1623
  int hw_subframe = 0; // 0..NUM_ENB_THREADS-1 => 0..9
1624
  
1625
  unsigned int rx_pos = 0;
1626
  unsigned int tx_pos = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
1627
#endif
1628
  int CC_id=0;	
1629
  struct timespec trx_time0, trx_time1, trx_time2;
1630

1631
#ifdef RTAI
1632
  RT_TASK* task = rt_task_init_schmod(nam2num("eNBmain"), 0, 0, 0, SCHED_FIFO, 0xF);
1633
#else
1634
#ifdef LOWLATENCY
1635 1636 1637
  struct sched_attr attr;
  unsigned int flags = 0;

Raymond Knopp's avatar
 
Raymond Knopp committed
1638 1639 1640 1641
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
1642

1643
  /* This creates a .2 ms  reservation */
Raymond Knopp's avatar
 
Raymond Knopp committed
1644
  attr.sched_policy = SCHED_DEADLINE;
navid's avatar
navid committed
1645
  attr.sched_runtime  = (0.3 * 100) * 10000;
1646 1647
  attr.sched_deadline = (0.9 * 100) * 10000;
  attr.sched_period   = 1 * 1000000;
1648

Lionel Gauthier's avatar
Lionel Gauthier committed
1649

Raymond Knopp's avatar
 
Raymond Knopp committed
1650 1651 1652 1653
  /* 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");
     }*/
1654

1655
  if (sched_setattr(0, &attr, flags) < 0 ) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1656 1657 1658 1659
    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",
1660
          gettid(),sched_getcpu());
Raymond Knopp's avatar
 
Raymond Knopp committed
1661
  }
1662

1663
#endif
1664 1665
#endif

1666 1667 1668 1669 1670
  // stop early, if an exit is requested
  // FIXME really neccessary?
  if (oai_exit)
    goto eNB_thread_cleanup;

1671
#ifdef RTAI
1672
  printf( "[SCHED][eNB] Started eNB main thread (id %p)\n", task );
Raymond Knopp's avatar
 
Raymond Knopp committed
1673
#else
1674
  printf( "[SCHED][eNB] Started eNB main thread on CPU %d TID %d\n", sched_getcpu(), gettid());
1675 1676 1677
#endif

#ifdef HARD_RT
1678
  rt_make_hard_real_time();
1679 1680
#endif

1681 1682 1683 1684 1685 1686 1687 1688
  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;
1689

1690 1691
  printf( "waiting for sync (eNB_thread)\n" );
  pthread_mutex_lock( &sync_mutex );
1692

1693 1694
  while (sync_var<0)
    pthread_cond_wait( &sync_cond, &sync_mutex );
1695

1696
  pthread_mutex_unlock(&sync_mutex);
1697

1698 1699
  printf( "got sync (eNB_thread)\n" );

1700
  int frame = 0;
1701

1702
#ifndef EXMIMO
1703 1704
  spp        = openair0_cfg[0].samples_per_packet;
  tx_pos     = openair0_cfg[0].tx_scheduling_advance;
1705
#endif
1706

1707 1708 1709 1710
#if defined(ENABLE_ITTI)
  wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB);
#endif 

1711 1712
  while (!oai_exit) {
    start_meas( &softmodem_stats_mt );
Raymond Knopp's avatar
 
Raymond Knopp committed
1713

1714
#ifdef EXMIMO
1715 1716
    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]);
1717 1718
    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);
1719 1720 1721 1722
    //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];
1723

1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734
    //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;
1735

1736
      if (diff<0)
1737
        diff = diff + 150;
1738

1739 1740 1741 1742
      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)))) {
1743

1744 1745 1746 1747
      // 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);
      
1748
      if (exit_missed_slots==1) {
1749 1750
        stop_meas(&softmodem_stats_mt);
        exit_fun("[HW][eNB] missed slot");
1751
      } else {
1752
        num_missed_slots++;
1753
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_MISSED_SLOTS_ENB,num_missed_slots );
1754
      }
1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776

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

    
1777
    }
1778

1779
    if (diff>8)
1780 1781
      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);
1782

1783 1784
    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);
1785 1786

    delay_cnt = 0;
1787

1788 1789 1790 1791
    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);
1792
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP,1);
1793
      ret = rt_sleep_ns(diff*DAQ_PERIOD);
1794 1795
      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);
1796

1797 1798
      if (ret)
        LOG_D(HW,"eNB Frame %d, time %llu: rt_sleep_ns returned %d\n",frame, time_in);
1799

Raymond Knopp's avatar
 
Raymond Knopp committed
1800
      hw_slot = (((((volatile unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15;
1801 1802 1803
      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());
1804
      delay_cnt++;
1805

1806 1807 1808 1809 1810
      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");
      }
1811

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1814
      if ((mbox_current>=135) && (mbox_target<15)) //handle the frame wrap-arround
1815
        diff = 150-mbox_current+mbox_target;
Raymond Knopp's avatar
 
Raymond Knopp committed
1816
      else if ((mbox_current<15) && (mbox_target>=135))
1817
        diff = -150+mbox_target-mbox_current;
Raymond Knopp's avatar
 
Raymond Knopp committed
1818
      else
1819 1820
        diff = mbox_target - mbox_current;
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1821

1822
#else  // EXMIMO
1823 1824
    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 );
1825
    tx_launched = 0;
1826

1827
    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
1828

1829
      unsigned int rxs;
Raymond Knopp's avatar
 
Raymond Knopp committed
1830
#ifndef USRP_DEBUG
1831 1832 1833
      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
1834

1835
      clock_gettime( CLOCK_MONOTONIC, &trx_time0 );
1836

1837
       start_meas( &softmodem_stats_hw );
1838

1839
      openair0_timestamp timestamp;
1840 1841
      int i=0;
      // prepare rx buffer pointers
1842
      for (i=0; i<PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx; i++)
1843 1844 1845 1846 1847 1848 1849
        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,
1850 1851
				     PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx);
      
1852
      stop_meas( &softmodem_stats_hw );
1853 1854 1855
      if (frame > 50) { 
	  clock_gettime( CLOCK_MONOTONIC, &trx_time1 );
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
1856

navid's avatar
navid committed
1857
      if (frame > 20){ 
1858 1859 1860
	if (rxs != spp)
	  exit_fun( "problem receiving samples" );
      }
1861
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
1862

1863
      // Transmit TX buffer based on timestamp from RX
1864 1865 1866 1867 1868 1869
    
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
      // prepare tx buffer pointers
      for (i=0; i<PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx; i++)
	txp[i] = (void*)&txdata[i][tx_pos];
      // if symb_written < spp ==> error 
navid's avatar
navid committed
1870
      if (frame > 50) {
1871
	openair0.trx_write_func(&openair0,
1872
				(timestamp+(openair0_cfg[card].tx_scheduling_advance)-openair0_cfg[card].tx_sample_advance),
1873 1874 1875 1876
				txp,
				spp,
				PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx,
				1);
navid's avatar
navid committed
1877 1878
      }
      
1879
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, timestamp&0xffffffff );
1880
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp+(openair0_cfg[card].tx_scheduling_advance)-openair0_cfg[card].tx_sample_advance)&0xffffffff );
1881 1882

      stop_meas( &softmodem_stats_mt );
1883 1884
      if (frame > 50) { 
	  clock_gettime( CLOCK_MONOTONIC, &trx_time2 );
Aikaterini's avatar
Aikaterini committed
1885
	  //update_difftimes(trx_time1, trx_time2);
1886 1887
      }

1888

1889
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE,0);
1890 1891 1892 1893
#else
      // USRP_DEBUG is active
      rt_sleep_ns(1000000);
#endif
1894 1895 1896 1897 1898 1899
      /* FT configurable tx lauch delay (in slots): txlaunch_wait, txlaunch_wait_slotcount is device specific and 
	 set in the corresponding library (with txlaunch_wait=1 and txlaunch_wait_slotcount=1 the check is as it previously was) */
      /* old check:
	 if ((frame>50) &&
	 (tx_launched == 0) &&
	 (rx_pos >= (((2*hw_subframe)+1)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))) {*/
Aikaterini's avatar
Aikaterini committed
1900
      if ( (frame>50) && (tx_launched == 0) &&
1901 1902
	   ((openair0_cfg[card].txlaunch_wait == 0) ||
	    ((openair0_cfg[card].txlaunch_wait == 1) &&
1903
	     (rx_pos >= (((2*hw_subframe)+openair0_cfg[card].txlaunch_wait_slotcount)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))))) { 
1904
	
1905
        tx_launched = 1;
1906

1907
        for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935
          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;

1936 1937
      if (tx_pos >= openair0_cfg[card].samples_per_frame)
        tx_pos -= openair0_cfg[card].samples_per_frame;
1938 1939
    }

1940 1941
    if (rx_pos >= openair0_cfg[card].samples_per_frame)
      rx_pos -= openair0_cfg[card].samples_per_frame;
1942

Raymond Knopp's avatar
 
Raymond Knopp committed
1943 1944

#endif // USRP
1945

1946
    if (oai_exit) break;
Raymond Knopp's avatar
 
Raymond Knopp committed
1947

1948 1949 1950 1951 1952
    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;
1953

1954 1955
      if (time_diff < timing_info.time_min)
        timing_info.time_min = time_diff;
1956

1957 1958
      if (time_diff > timing_info.time_max)
        timing_info.time_max = time_diff;
1959

1960 1961 1962 1963 1964 1965
      timing_info.time_avg += time_diff;
    }

    timing_info.n_samples++;

    if ((slot&1) == 1) {
1966
      // odd slot
1967
#ifdef EXMIMO
1968
      int sf = ((slot>>1)+1)%10;
Raymond Knopp's avatar
 
Raymond Knopp committed
1969
#else
1970
      int sf = hw_subframe;
Raymond Knopp's avatar
 
Raymond Knopp committed
1971
#endif
1972 1973
      if (frame>50) {
	for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1974
#ifdef EXMIMO
1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989
	  
	  if (pthread_mutex_lock(&PHY_vars_eNB_g[0][CC_id]->proc[sf].mutex_tx) != 0) {
	    LOG_E(PHY,"[eNB] ERROR pthread_mutex_lock for eNB TX thread %d (IC %d)\n",sf,PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_tx);
	  } else {
	    //          LOG_I(PHY,"[eNB] Waking up eNB process %d (IC %d)\n",sf,PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt);
	    PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_tx++;
	    pthread_mutex_unlock(&PHY_vars_eNB_g[0][CC_id]->proc[sf].mutex_tx);
	    
	    if (PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_tx == 0) {
	      if (pthread_cond_signal(&PHY_vars_eNB_g[0][CC_id]->proc[sf].cond_tx) != 0) {
		LOG_E(PHY,"[eNB] ERROR pthread_cond_signal for eNB TX thread %d\n",sf);
		exit_fun("nothing to add");
	      }
	    } else {
	      LOG_W(PHY,"[eNB] Frame %d, eNB TX thread %d busy!!\n",PHY_vars_eNB_g[0][CC_id]->proc[sf].frame_tx,sf);
1990
	      exit_fun("nothing to add");
1991 1992 1993
	    }
	  }
	  
Raymond Knopp's avatar
 
Raymond Knopp committed
1994 1995
#endif

1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018
	  if (pthread_mutex_lock(&PHY_vars_eNB_g[0][CC_id]->proc[sf].mutex_rx) != 0) {
	    LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB RX thread %d (IC %d)\n", sf, PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_rx );
	    exit_fun( "error locking mutex_rx" );
	    break;
	  }
	  
	  int cnt_rx = ++PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_rx;
	  
	  pthread_mutex_unlock( &PHY_vars_eNB_g[0][CC_id]->proc[sf].mutex_rx );
	  
	  if (cnt_rx == 0) {
	    // the thread was presumably waiting where it should and can now be woken up
	    if (pthread_cond_signal(&PHY_vars_eNB_g[0][CC_id]->proc[sf].cond_rx) != 0) {
	      LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB RX thread %d\n", sf );
	      exit_fun( "ERROR pthread_cond_signal" );
	      break;
	    }
	  } else {
	    LOG_W( PHY, "[eNB] Frame %d, eNB RX thread %d busy!! instance_cnt %d CC_id %d\n", PHY_vars_eNB_g[0][CC_id]->proc[sf].frame_rx, sf, PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_rx, CC_id );
	    exit_fun( "RX thread busy" );
	    break;
	  }
	}
Raymond Knopp's avatar
 
Raymond Knopp committed
2019
      }
2020 2021 2022 2023
    }

#ifdef EXMIMO
    slot++;
2024

2025 2026 2027 2028
    if (slot == 20) {
      frame++;
      slot = 0;
    }
2029

Raymond Knopp's avatar
 
Raymond Knopp committed
2030
#else
2031 2032
    hw_subframe++;
    slot += 2;
2033

2034
    if (hw_subframe == NUM_ENB_THREADS) {
2035
      // the radio frame is complete, start over
2036 2037 2038 2039
      hw_subframe = 0;
      frame++;
      slot = 1;
    }
2040 2041

#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2042

2043
#if defined(ENABLE_ITTI)
2044
    itti_update_lte_time( frame, slot );
2045
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2046
  }
2047 2048

eNB_thread_cleanup:
Raymond Knopp's avatar
 
Raymond Knopp committed
2049
#ifdef DEBUG_THREADS
2050
  printf( "eNB_thread: finished, ran %d times.\n", frame );
Raymond Knopp's avatar
 
Raymond Knopp committed
2051
#endif
2052

2053
#ifdef HARD_RT
Raymond Knopp's avatar
 
Raymond Knopp committed
2054
  rt_make_soft_real_time();
2055 2056
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
2057
#ifdef DEBUG_THREADS
2058
  printf( "Exiting eNB_thread ..." );
Raymond Knopp's avatar
 
Raymond Knopp committed
2059 2060
#endif
  // clean task
2061
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
2062
  rt_task_delete(task);
2063
#endif
2064 2065

  eNB_thread_status = 0;
2066

2067
  // print_difftimes();
2068

2069
  return &eNB_thread_status;
Raymond Knopp's avatar
 
Raymond Knopp committed
2070
}
2071

2072

Raymond Knopp's avatar
 
Raymond Knopp committed
2073

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2074

2075 2076
static void get_options (int argc, char **argv)
{
2077 2078 2079
  int c;
  //  char                          line[1000];
  //  int                           l;
2080
  int k,i;//,j,k;
2081
#if defined(OAI_USRP) || defined(CPRIGW)
2082
  int clock_src;
2083
#endif
2084 2085 2086 2087 2088
  int CC_id;
#ifdef EXMIMO
  char rxg_fname[256], line[1000];
  FILE *rxg_fd;
  int l;
2089
#endif
2090 2091 2092



2093 2094

  const Enb_properties_array_t *enb_properties;
2095

2096 2097 2098 2099 2100 2101 2102
  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,
2103
    LONG_OPTION_NO_L2_CONNECT,
Raymond Knopp's avatar
 
Raymond Knopp committed
2104
    LONG_OPTION_CALIB_PRACH_TX,
2105 2106
    LONG_OPTION_RXGAIN,
    LONG_OPTION_TXGAIN,
2107
    LONG_OPTION_SCANCARRIER,
2108 2109 2110
    LONG_OPTION_MAXPOWER,
    LONG_OPTION_DUMP_FRAME,
    LONG_OPTION_LOOPMEMORY
2111
  };
2112

2113 2114 2115 2116 2117 2118 2119
  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
2120 2121 2122 2123
    {"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},
2124
    {"ue-max-power",   required_argument,  NULL, LONG_OPTION_MAXPOWER},
2125 2126
    {"ue-dump-frame", no_argument, NULL, LONG_OPTION_DUMP_FRAME},
    {"loop-memory", required_argument, NULL, LONG_OPTION_LOOPMEMORY},
2127 2128 2129
    {NULL, 0, NULL, 0}
  };

2130
  while ((c = getopt_long (argc, argv, "A:a:C:dEK:g:F:G:hqO:m:SUVRM:r:P:Ws:t:Tx:",long_options,NULL)) != -1) {
2131
    switch (c) {
2132 2133 2134 2135 2136
    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];

2137 2138 2139 2140
    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;
2141

2142 2143 2144 2145 2146
    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;
2147

2148 2149 2150 2151
    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
2152
      break;
2153

2154 2155 2156 2157 2158
    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;
2159

2160 2161 2162
    case LONG_OPTION_DEBUG_UE_PRACH:
      mode = debug_prach;
      break;
2163

2164 2165 2166
    case LONG_OPTION_NO_L2_CONNECT:
      mode = no_L2_connect;
      break;
2167

Raymond Knopp's avatar
 
Raymond Knopp committed
2168 2169 2170 2171
    case LONG_OPTION_CALIB_PRACH_TX:
      mode = calib_prach_tx;
      break;

2172
    case LONG_OPTION_RXGAIN:
2173 2174
      for (i=0; i<4; i++)
        rx_gain[0][i] = atof(optarg);
2175

2176
      break;
2177

2178 2179 2180
    case LONG_OPTION_TXGAIN:
      for (i=0; i<4; i++)
        tx_gain[0][i] = atof(optarg);
2181

2182
      break;
2183

2184 2185 2186 2187 2188
    case LONG_OPTION_SCANCARRIER:
      UE_scan_carrier=1;

      break;

2189 2190 2191 2192 2193 2194 2195 2196
    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;
2197
     break;   
2198 2199 2200 2201
    case 'A':
      timing_advance = atoi (optarg);
      break;

2202
    case 'C':
2203 2204 2205 2206 2207 2208
      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]);
2209
      }
2210

2211
      UE_scan=0;
2212

2213
      break;
2214

Florian Kaltenberger's avatar
Florian Kaltenberger committed
2215 2216 2217 2218
    case 'a':
      chain_offset = atoi(optarg);
      break;

2219 2220 2221 2222
    case 'd':
#ifdef XFORMS
      do_forms=1;
      printf("Running with XFORMS!\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2223
#endif
2224
      break;
2225 2226 2227 2228
      
    case 'E':
      threequarter_fs=1;
      break;
2229

2230 2231 2232
    case 'K':
#if defined(ENABLE_ITTI)
      itti_dump_file = strdup(optarg);
2233
#else
2234
      printf("-K option is disabled when ENABLE_ITTI is not defined\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
2235
#endif
2236
      break;
2237

2238 2239 2240
    case 'O':
      conf_config_file_name = optarg;
      break;
2241

2242 2243 2244
    case 'U':
      UE_flag = 1;
      break;
2245

2246 2247 2248
    case 'm':
      target_dl_mcs = atoi (optarg);
      break;
2249

2250 2251 2252
    case 't':
      target_ul_mcs = atoi (optarg);
      break;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2253
#ifdef OPENAIR2
2254

2255 2256 2257 2258 2259 2260 2261
    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");
      /*
2262 2263 2264
      if (optarg == NULL){
      in_ip[0] =NULL;
      printf("Enabling OPT for wireshark for local interface");
2265
      } else {
2266 2267 2268
      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);
2269 2270 2271
      }
      */
      break;
2272

2273
    case 'P':
2274 2275
      opt_type = OPT_PCAP;
      opt_enabled=1;
2276 2277 2278 2279 2280

      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");
2281
      } else {
2282 2283 2284
        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);
2285
      }
2286 2287

      break;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
2288
#endif
2289

Raymond Knopp's avatar
 
Raymond Knopp committed
2290 2291 2292
    case 'V':
      ouput_vcd = 1;
      break;
2293

Raymond Knopp's avatar
 
Raymond Knopp committed
2294
    case  'q':
Raymond Knopp's avatar
 
Raymond Knopp committed
2295 2296
      opp_enabled = 1;
      break;
2297

Raymond Knopp's avatar
 
Raymond Knopp committed
2298 2299 2300
    case  'R' :
      online_log_messages =1;
      break;
2301

Raymond Knopp's avatar
 
Raymond Knopp committed
2302
    case 'r':
2303
      UE_scan = 0;
2304

2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330
      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
2331
      }
2332

2333
      break;
2334

Raymond Knopp's avatar
 
Raymond Knopp committed
2335
    case 's':
2336
#if defined(OAI_USRP) || defined(CPRIGW)
Raymond Knopp's avatar
 
Raymond Knopp committed
2337 2338

      clock_src = atoi(optarg);
2339

Raymond Knopp's avatar
 
Raymond Knopp committed
2340
      if (clock_src == 0) {
2341 2342 2343 2344 2345
        //  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
2346
      }
2347

Raymond Knopp's avatar
 
Raymond Knopp committed
2348 2349 2350 2351
#else
      printf("Note: -s not defined for ExpressMIMO2\n");
#endif
      break;
2352

2353 2354 2355 2356
    case 'S':
      exit_missed_slots=0;
      printf("Skip exit for missed slots\n");
      break;
2357

2358
    case 'g':
Raymond Knopp's avatar
 
Raymond Knopp committed
2359
      glog_level=atoi(optarg); // value between 1 - 9
2360
      break;
2361 2362

    case 'F':
2363
#ifdef EXMIMO
2364 2365
      sprintf(rxg_fname,"%srxg.lime",optarg);
      rxg_fd = fopen(rxg_fname,"r");
2366

2367
      if (rxg_fd) {
2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385
        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);

2386
#endif
2387
      break;
2388

2389 2390 2391
    case 'G':
      glog_verbosity=atoi(optarg);// value from 0, 0x5, 0x15, 0x35, 0x75
      break;
2392

2393 2394
    case 'x':
      transmission_mode = atoi(optarg);
2395

2396
      if (transmission_mode > 2) {
2397 2398
        printf("Transmission mode > 2 (%d) not supported for the moment\n",transmission_mode);
        exit(-1);
2399
      }
2400
      break;
2401

2402 2403 2404
    case 'T':
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) 
	frame_parms[CC_id]->frame_type = TDD;
2405
      break;
2406

2407 2408 2409 2410
    case 'h':
      help ();
      exit (-1);
       
Raymond Knopp's avatar
 
Raymond Knopp committed
2411
    default:
2412 2413
      help ();
      exit (-1);
Raymond Knopp's avatar
 
Raymond Knopp committed
2414
      break;
2415 2416
    }
  }
2417

Raymond Knopp's avatar
 
Raymond Knopp committed
2418 2419
  if (UE_flag == 0)
    AssertFatal(conf_config_file_name != NULL,"Please provide a configuration file\n");
2420 2421


Raymond Knopp's avatar
 
Raymond Knopp committed
2422
  if ((UE_flag == 0) && (conf_config_file_name != NULL)) {
2423
    int i,j;
2424

Raymond Knopp's avatar
 
Raymond Knopp committed
2425
    NB_eNB_INST = 1;
2426

Raymond Knopp's avatar
 
Raymond Knopp committed
2427 2428
    /* Read eNB configuration file */
    enb_properties = enb_config_init(conf_config_file_name);
2429

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

Raymond Knopp's avatar
 
Raymond Knopp committed
2434
    /* Update some simulation parameters */
2435
    for (i=0; i < enb_properties->number; i++) {
2436
      AssertFatal (MAX_NUM_CCs == enb_properties->properties[i]->nb_cc,
2437 2438 2439
                   "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);

2440 2441
      for (j=0; j<enb_properties->properties[i]->nb_rrh_gw; j++) {
	
2442 2443 2444 2445 2446
	if (enb_properties->properties[i]->rrh_gw_config[j].active == 1 ) {
	  local_remote_radio = BBU_REMOTE_RADIO_HEAD;
	  eth_params = (eth_params_t*)malloc(sizeof(eth_params_t));
	  memset(eth_params, 0, sizeof(eth_params_t));
	 
2447 2448 2449 2450 2451 2452 2453
	  printf( "\n\tRRH GW %d config for eNB %u:\n\n", j, i);
	  printf( "\tinterface name :       \t%s:\n",enb_properties->properties[i]->rrh_gw_if_name);
	  printf( "\tlocal address  :       \t%s:\n",enb_properties->properties[i]->rrh_gw_config[j].local_address);
	  printf( "\tlocal port     :       \t%d:\n",enb_properties->properties[i]->rrh_gw_config[j].local_port);
	  printf( "\tremote address :       \t%s:\n",enb_properties->properties[i]->rrh_gw_config[j].remote_address);
	  printf( "\tremote port    :       \t%d:\n",enb_properties->properties[i]->rrh_gw_config[j].remote_port);
	  printf( "\ttransport      :       \t%s Ethernet:\n\n",(enb_properties->properties[i]->rrh_gw_config[j].raw == 1)? "RAW" : "UDP");
2454 2455 2456 2457 2458 2459 2460 2461 2462 2463
	  
	  eth_params->local_if_name             = enb_properties->properties[i]->rrh_gw_if_name;
	  eth_params->my_addr                   = enb_properties->properties[i]->rrh_gw_config[j].local_address;
	  eth_params->my_port                   = enb_properties->properties[i]->rrh_gw_config[j].local_port;
	  eth_params->remote_addr               = enb_properties->properties[i]->rrh_gw_config[j].remote_address;
	  eth_params->remote_port               = enb_properties->properties[i]->rrh_gw_config[j].remote_port;
	  eth_params->transp_preference         = enb_properties->properties[i]->rrh_gw_config[j].raw;
 
	} else {
	  local_remote_radio = BBU_LOCAL_RADIO_HEAD; 
2464 2465 2466 2467
	}
	
      }

2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478
      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];
2479
        frame_parms[CC_id]->nb_antenna_ports_eNB  =  enb_properties->properties[i]->nb_antennas_tx[CC_id];
2480 2481
        frame_parms[CC_id]->nb_antennas_rx      =  enb_properties->properties[i]->nb_antennas_rx[CC_id];
        //} // j
Raymond Knopp's avatar
 
Raymond Knopp committed
2482 2483
      }

2484

2485
#ifdef OPENAIR2
2486

2487 2488 2489
      init_all_otg(0);
      g_otg->seed = 0;
      init_seeds(g_otg->seed);
2490 2491 2492 2493 2494 2495 2496 2497 2498 2499

      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");
2500
      }
2501

2502
      init_predef_traffic(enb_properties->properties[i]->num_otg_elements, 1);
2503

2504
#endif
2505

2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519
      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
2520 2521 2522 2523 2524 2525
# 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
2526 2527 2528
#if defined (ENABLE_SECURITY)
      osa_log_level                  = enb_properties->properties[i]->osa_log_level;
      osa_log_verbosity              = enb_properties->properties[i]->osa_log_verbosity;
2529
#endif
Florian Kaltenberger's avatar
Florian Kaltenberger committed
2530

Raymond Knopp's avatar
 
Raymond Knopp committed
2531
      // adjust the log
2532
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
2533 2534 2535 2536 2537 2538 2539 2540 2541 2542
        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
2543
      } // CC_id
2544
    }// i
2545 2546 2547 2548 2549 2550 2551 2552
  } 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
2553
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
2554
}
2555

2556 2557
int main( int argc, char **argv )
{
2558
  int i,aa,card=0;
Lionel Gauthier's avatar
Lionel Gauthier committed
2559
#if defined (XFORMS) || defined (EMOS) || defined (EXMIMO)
Raymond Knopp's avatar
 
Raymond Knopp committed
2560
  void *status;
2561
#endif
2562

Raymond Knopp's avatar
 
Raymond Knopp committed
2563
  int CC_id;
Raymond Knopp's avatar
 
Raymond Knopp committed
2564
  uint16_t Nid_cell = 0;
2565
  uint8_t  cooperation_flag=0,  abstraction_flag=0;
2566
#ifndef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
2567
  uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2;
2568 2569 2570
#endif

#ifdef ENABLE_TCXO
Raymond Knopp's avatar
 
Raymond Knopp committed
2571
  unsigned int tcxo = 114;
2572 2573
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
2574
#if defined (XFORMS)
2575 2576
  int ret;
#endif
2577
#if defined (EMOS) || (! defined (RTAI))
Raymond Knopp's avatar
 
Raymond Knopp committed
2578
  int error_code;
2579
#endif
2580

2581 2582 2583 2584 2585
#ifdef DEBUG_CONSOLE
  setvbuf(stdout, NULL, _IONBF, 0);
  setvbuf(stderr, NULL, _IONBF, 0);
#endif

2586 2587 2588
  PHY_VARS_UE *UE[MAX_NUM_CCs];

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

2591
  memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
Raymond Knopp's avatar
 
Raymond Knopp committed
2592
  set_latency_target();
2593

2594
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2595 2596
    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 */
2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608
    frame_parms[CC_id]->frame_type            = FDD;
    frame_parms[CC_id]->tdd_config            = 3;
    frame_parms[CC_id]->tdd_config_S          = 0;
    frame_parms[CC_id]->N_RB_DL               = 100;
    frame_parms[CC_id]->N_RB_UL               = 100;
    frame_parms[CC_id]->Ncp                   = NORMAL;
    frame_parms[CC_id]->Ncp_UL                = NORMAL;
    frame_parms[CC_id]->Nid_cell              = Nid_cell;
    frame_parms[CC_id]->num_MBSFN_config      = 0;
    frame_parms[CC_id]->nb_antenna_ports_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
2609
  }
2610

2611 2612 2613 2614 2615
  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];
2616
    //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
2617
  }
2618 2619
  logInit();
 
2620
  get_options (argc, argv); //Command-line options
2621 2622 2623
 
  
  // initialize the log (see log.h for details)
Florian Kaltenberger's avatar
Florian Kaltenberger committed
2624 2625
  set_glog(glog_level, glog_verbosity);

2626 2627
  //randominit (0);
  set_taus_seed (0);
Raymond Knopp's avatar
 
Raymond Knopp committed
2628

2629 2630
  if (UE_flag==1) {
    printf("configuring for UE\n");
2631

2632
    set_comp_log(HW,      LOG_INFO,  LOG_HIGH, 1);
2633 2634 2635 2636 2637 2638
    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);
2639
#if defined(ENABLE_ITTI)
2640
    set_comp_log(EMU,     LOG_INFO,   LOG_MED, 1);
2641
# if defined(ENABLE_USE_MME)
2642
    set_comp_log(NAS,     LOG_INFO,   LOG_HIGH, 1);
2643 2644
# endif
#endif
2645 2646
  } else {
    printf("configuring for eNB\n");
2647

2648
    set_comp_log(HW,      hw_log_level, hw_log_verbosity, 1);
2649
#ifdef OPENAIR2
2650 2651 2652 2653 2654
    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);

2655
#else
2656
    set_comp_log(PHY,     LOG_INFO,   LOG_HIGH, 1);
2657
#endif
2658 2659 2660 2661
    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);
2662
#if defined(ENABLE_ITTI)
2663
    set_comp_log(EMU,     LOG_INFO,   LOG_MED, 1);
2664
# if defined(ENABLE_USE_MME)
2665 2666 2667 2668
    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);
2669
# endif
2670
#if defined(ENABLE_SECURITY)
2671
    set_comp_log(OSA,    osa_log_level,   osa_log_verbosity, 1);
2672
#endif
2673
#endif
2674
#ifdef LOCALIZATION
2675 2676 2677 2678 2679 2680 2681 2682 2683
    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
2684
    }
2685
  }
2686

Raymond Knopp's avatar
 
Raymond Knopp committed
2687 2688
  if (ouput_vcd) {
    if (UE_flag==1)
2689
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_UE.vcd");
Raymond Knopp's avatar
 
Raymond Knopp committed
2690
    else
2691
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_eNB.vcd");
Raymond Knopp's avatar
 
Raymond Knopp committed
2692
  }
2693

2694
  if (opp_enabled ==1){
2695
    reset_opp_meas();
2696 2697
  }
  cpuf=get_cpu_freq_GHz();
2698

2699
#if defined(ENABLE_ITTI)
2700

Raymond Knopp's avatar
 
Raymond Knopp committed
2701 2702
  if (UE_flag == 1) {
    log_set_instance_type (LOG_INSTANCE_UE);
2703
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
2704 2705
    log_set_instance_type (LOG_INSTANCE_ENB);
  }
2706

Raymond Knopp's avatar
 
Raymond Knopp committed
2707
  itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, itti_dump_file);
2708
 
2709 2710
  // initialize mscgen log after ITTI
  MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX);
2711 2712
#endif
 
2713
#ifdef OPENAIR2
2714

2715 2716
  if (opt_type != OPT_NONE) {
    radio_type_t radio_type;
2717

2718 2719
    if (frame_parms[0]->frame_type == FDD)
      radio_type = RADIO_TYPE_FDD;
2720
    else
2721
      radio_type = RADIO_TYPE_TDD;
2722

2723 2724 2725
    if (init_opt(in_path, in_ip, NULL, radio_type) == -1)
      LOG_E(OPT,"failed to run OPT \n");
  }
2726

2727
#endif
2728
#ifdef PDCP_USE_NETLINK
Raymond Knopp's avatar
 
Raymond Knopp committed
2729
  netlink_init();
2730 2731 2732
#if defined(PDCP_USE_NETLINK_QUEUES)
  pdcp_netlink_init();
#endif
2733 2734
#endif

2735
#if !defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
2736 2737 2738
  // to make a graceful exit when ctrl-c is pressed
  signal(SIGSEGV, signal_handler);
  signal(SIGINT, signal_handler);
2739
#endif
2740 2741

#ifndef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
2742 2743 2744 2745
  check_clock();
#endif

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

2749 2750 2751 2752 2753 2754
    if (UE_flag==0) {

    } else {
      //UE_flag==1
      frame_parms[CC_id]->nb_antennas_tx     = 1;
      frame_parms[CC_id]->nb_antennas_rx     = 1;
2755
      frame_parms[CC_id]->nb_antenna_ports_eNB = (transmission_mode == 1 || transmission_mode ==7) ? 1 : 2; //initial value overwritten by initial sync later
2756 2757
    }

Raymond Knopp's avatar
 
Raymond Knopp committed
2758 2759 2760 2761 2762 2763 2764 2765
    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;
2766
    frame_parms[CC_id]->threequarter_fs = threequarter_fs;
2767 2768
    init_ul_hopping(frame_parms[CC_id]);
    init_frame_parms(frame_parms[CC_id],1);
2769 2770
    //   phy_init_top(frame_parms[CC_id]);
    phy_init_lte_top(frame_parms[CC_id]);
Raymond Knopp's avatar
 
Raymond Knopp committed
2771 2772 2773
  }


2774
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2775
    //init prach for openair1 test
2776
    frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22;
Raymond Knopp's avatar
 
Raymond Knopp committed
2777
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1;
2778
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2779 2780 2781
    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
2782
    // N_ZC = (prach_fmt <4)?839:139;
Raymond Knopp's avatar
 
Raymond Knopp committed
2783
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
2784 2785

  if (UE_flag==1) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2786 2787 2788
    NB_UE_INST=1;
    NB_INST=1;

Raymond Knopp's avatar
 
Raymond Knopp committed
2789 2790
    PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE**));
    PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_UE*)*MAX_NUM_CCs);
2791 2792

    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
2793 2794 2795 2796

      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
2797
#ifndef OPENAIR2
2798 2799 2800 2801 2802 2803 2804 2805 2806

      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
2807
      }
2808

2809
#endif
2810 2811 2812


      UE[CC_id]->UE_scan = UE_scan;
2813
      UE[CC_id]->UE_scan_carrier = UE_scan_carrier;
2814 2815 2816
      UE[CC_id]->mode    = mode;

      compute_prach_seq(&UE[CC_id]->lte_frame_parms.prach_config_common,
2817 2818 2819
                        UE[CC_id]->lte_frame_parms.frame_type,
                        UE[CC_id]->X_u);

2820
      UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1234;
2821
#ifndef OPENAIR2
2822
      UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1235;
2823
#endif
2824

2825
#ifdef EXMIMO
2826

2827 2828 2829 2830
      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
2831
      }
2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850

      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
2851
      }
2852

2853
#else
2854
      UE[CC_id]->rx_total_gain_dB =  (int)rx_gain[CC_id][0];
2855
#endif
2856

2857
      UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id];
2858

2859 2860


2861
#ifdef EXMIMO
2862

Raymond Knopp's avatar
 
Raymond Knopp committed
2863
      //N_TA_offset
2864
      if (UE[CC_id]->lte_frame_parms.frame_type == TDD) {
2865 2866 2867 2868 2869 2870 2871 2872
        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
2873
      }
2874

2875
#else
Raymond Knopp's avatar
 
Raymond Knopp committed
2876
      //already taken care of in lte-softmodem
2877
      UE[CC_id]->N_TA_offset = 0;
2878
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2879
    }
2880

Raymond Knopp's avatar
 
Raymond Knopp committed
2881 2882 2883 2884
    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;
2885 2886 2887



Raymond Knopp's avatar
 
Raymond Knopp committed
2888
    //  printf("tx_max_power = %d -> amp %d\n",tx_max_power,get_tx_amp(tx_max_power,tx_max_power));
2889 2890 2891 2892 2893 2894
  } 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++) {
2895
      PHY_vars_eNB_g[0][CC_id] = init_lte_eNB(frame_parms[CC_id],0,frame_parms[CC_id]->Nid_cell,cooperation_flag,transmission_mode,abstraction_flag);
2896 2897
      PHY_vars_eNB_g[0][CC_id]->CC_id = CC_id;

2898
#ifndef OPENAIR2
2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914

      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
2915

2916
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
2917

2918
      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
2919

2920
#else
2921 2922 2923
      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
2924

2925 2926 2927
      // 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
2928

2929
#endif
2930

2931
#ifdef EXMIMO
2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942

      //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
2943
      }
2944

2945
#else
2946
      //already taken care of in lte-softmodem.c
2947 2948
      PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 0;
#endif
2949

2950
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
2951 2952


2953 2954 2955 2956 2957 2958 2959 2960 2961
    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;

  }
2962 2963 2964 2965
#ifndef RTAI
  fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx);
  cpuf=get_cpu_freq_GHz();
#endif 
2966

Raymond Knopp's avatar
 
Raymond Knopp committed
2967
  dump_frame_parms(frame_parms[0]);
2968

2969 2970 2971
  for (card=0; card<MAX_CARDS; card++) {

    if(frame_parms[0]->N_RB_DL == 100) {
2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983
      if (frame_parms[0]->threequarter_fs) {
	openair0_cfg[card].sample_rate=23.04e6;
	openair0_cfg[card].samples_per_frame = 230400; 
	openair0_cfg[card].tx_bw = 10e6;
	openair0_cfg[card].rx_bw = 10e6;
      }
      else {
	openair0_cfg[card].sample_rate=30.72e6;
	openair0_cfg[card].samples_per_frame = 307200; 
	openair0_cfg[card].tx_bw = 10e6;
	openair0_cfg[card].rx_bw = 10e6;
      }
2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999
    } else if(frame_parms[0]->N_RB_DL == 50) {
      openair0_cfg[card].sample_rate=15.36e6;
      openair0_cfg[card].samples_per_frame = 153600;
      openair0_cfg[card].tx_bw = 5e6;
      openair0_cfg[card].rx_bw = 5e6;
    } else if (frame_parms[0]->N_RB_DL == 25) {
      openair0_cfg[card].sample_rate=7.68e6;
      openair0_cfg[card].samples_per_frame = 76800;
      openair0_cfg[card].tx_bw = 2.5e6;
      openair0_cfg[card].rx_bw = 2.5e6;
    } else if (frame_parms[0]->N_RB_DL == 6) {
      openair0_cfg[card].sample_rate=1.92e6;
      openair0_cfg[card].samples_per_frame = 19200;
      openair0_cfg[card].tx_bw = 1.5e6;
      openair0_cfg[card].rx_bw = 1.5e6;
    }
3000 3001 3002 3003 3004 3005

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3006

3007 3008 3009 3010 3011 3012
    if (local_remote_radio == BBU_REMOTE_RADIO_HEAD) {      
      openair0_cfg[card].remote_addr    = eth_params->remote_addr;
      openair0_cfg[card].remote_port    = eth_params->remote_port;
      openair0_cfg[card].my_addr        = eth_params->my_addr;
      openair0_cfg[card].my_port        = eth_params->my_port;    
    }
3013

3014
    printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card,
3015 3016
           ((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
3017 3018
    openair0_cfg[card].Mod_id = 0;
#ifdef ETHERNET
3019 3020

    if (UE_flag) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3021
      printf("ETHERNET: Configuring UE ETH for %s:%d\n",rrh_UE_ip,rrh_UE_port);
3022
      openair0_cfg[card].remote_addr   = &rrh_UE_ip[0];
3023
      openair0_cfg[card].remote_port = rrh_UE_port;
3024 3025
    } 

3026
    openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL;
Raymond Knopp's avatar
 
Raymond Knopp committed
3027
#endif
3028

3029
    // in the case of the USRP, the following variables need to be initialized before the init
3030
    // since the USRP only supports one CC (for the moment), we initialize all the cards with first CC.
3031
    // in the case of EXMIMO2, these values are overwirtten in the function setup_eNB/UE_buffer
3032
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3033 3034
    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));
3035 3036

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

3038 3039 3040 3041 3042 3043 3044 3045
      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]);
      
3046
      openair0_cfg[card].autocal[i] = 1;
3047
      openair0_cfg[card].tx_gain[i] = tx_gain[0][i];
3048 3049 3050 3051
      if (UE_flag == 0) {
	openair0_cfg[card].rx_gain[i] = PHY_vars_eNB_g[0][0]->rx_total_gain_eNB_dB;
      }
      else {
3052
	openair0_cfg[card].rx_gain[i] = PHY_vars_UE_g[0][0]->rx_total_gain_dB;
3053
      }
3054

3055
#if 0  // UHD 3.8     
3056 3057
      switch(frame_parms[0]->N_RB_DL) {
      case 6:
3058
        openair0_cfg[card].rx_gain[i] -= 12;
3059 3060
        break;

3061
      case 25:
3062
        openair0_cfg[card].rx_gain[i] -= 6;
3063 3064
        break;

3065
      case 50:
3066 3067 3068 3069 3070
        openair0_cfg[card].rx_gain[i] -= 3;
        break;

      case 100:
        openair0_cfg[card].rx_gain[i] -= 0;
3071 3072
        break;

3073
      default:
3074
        break;
3075
      }
3076
#endif      
3077

Raymond Knopp's avatar
 
Raymond Knopp committed
3078
    }
3079

3080
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3081
  }
3082 3083 3084 3085 3086 3087
  /* device host type is set*/
  openair0.host_type = BBU_HOST;
  /* device type is initialized NONE_DEV (no RF device) when the RF device will be initiated device type will be set */
  openair0.type = NONE_DEV;
  /* transport type is initialized NONE_TP (no transport protocol) when the transport protocol will be initiated transport protocol type will be set */
  openair0.transp_type = NONE_TP;
navid's avatar
navid committed
3088
  openair0_cfg[0].log_level = glog_level;
3089

3090 3091 3092 3093 3094 3095 3096 3097 3098 3099
  int returns=-1;
  /* BBU can have either a local or a remote radio head */  
  if (local_remote_radio == BBU_LOCAL_RADIO_HEAD) { //local radio head active  - load library of radio head and initiate it
    if (mode!=loop_through_memory) {
      returns=openair0_device_load(&openair0, &openair0_cfg[0]);
      printf("openair0_device_init returns %d\n",returns);
      if (returns<0) {
	printf("Exiting, cannot initialize device\n");
	exit(-1);
      }
3100
    }
3101 3102 3103 3104 3105 3106 3107 3108 3109 3110
    else if (mode==loop_through_memory) {    
    }
  }  else { //remote radio head active - load library of transport protocol and initiate it 
    if (mode!=loop_through_memory) {
      returns=openair0_transport_load(&openair0, &openair0_cfg[0], eth_params);
      printf("openair0_transport_init returns %d\n",returns);
      if (returns<0) { 
	printf("Exiting, cannot initialize transport protocol\n");
	exit(-1);
      }
3111 3112 3113 3114
    }
    else if (mode==loop_through_memory) {    
    }
  }   
3115
  
3116
  printf("Done\n");
3117 3118 3119

  mac_xface = malloc(sizeof(MAC_xface));

3120
#ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
3121
  int eMBMS_active=0;
3122

Raymond Knopp's avatar
 
Raymond Knopp committed
3123
  l2_init(frame_parms[0],eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL,
3124 3125 3126 3127
          0,// cba_group_active
          0); // HO flag


3128 3129
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3130
  mac_xface->macphy_exit = &exit_fun;
3131

winckel's avatar
winckel committed
3132
#if defined(ENABLE_ITTI)
3133

Raymond Knopp's avatar
 
Raymond Knopp committed
3134
  if (create_tasks(UE_flag ? 0 : 1, UE_flag ? 1 : 0) < 0) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3135
    printf("cannot create ITTI tasks\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3136 3137
    exit(-1); // need a softer mode
  }
3138

Raymond Knopp's avatar
 
Raymond Knopp committed
3139
  printf("ITTI tasks created\n");
winckel's avatar
winckel committed
3140
#endif
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3141 3142

#ifdef OPENAIR2
3143
  if (UE_flag==1) {
3144
    printf("Filling UE band info\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3145
    fill_ue_band_info();
3146
    mac_xface->dl_phy_sync_success (0, 0, 0, 1);
3147
  } else
3148
    mac_xface->mrbch_phy_sync_failure (0, 0, 0);
3149

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3150
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3151

3152
  /* #ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
3153 3154 3155 3156 3157 3158
  //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
3159 3160 3161 3162 3163 3164
  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
3165 3166 3167
  }
  init_predef_traffic(UE_flag ? 1 : 0, UE_flag ? 0 : 1);
  //  }
3168
  #endif */
Raymond Knopp's avatar
 
Raymond Knopp committed
3169

3170
#ifdef EXMIMO
3171
  number_of_cards = openair0_num_detected_cards;
3172 3173
#else
  number_of_cards = 1;
3174
#endif
3175

3176

3177

3178
  for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3179
    rf_map[CC_id].card=0;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3180
    rf_map[CC_id].chain=CC_id+chain_offset;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3181
  }
3182

Raymond Knopp's avatar
 
Raymond Knopp committed
3183 3184
  // connect the TX/RX buffers
  if (UE_flag==1) {
3185
#ifdef OAI_USRP
3186
    openair_daq_vars.timing_advance = timing_advance;
3187
#else
3188
    openair_daq_vars.timing_advance = 160;
3189
#endif
3190
    if (setup_ue_buffers(UE,&openair0_cfg[0],rf_map)!=0) {
3191 3192 3193
      printf("Error setting up eNB buffer\n");
      exit(-1);
    }
3194

3195
    printf("Setting UE buffer to all-RX\n");
3196

3197
    // Set LSBs for antenna switch (ExpressMIMO)
3198
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3199
      for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++)
3200 3201
        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
3202
    }
3203

3204 3205 3206 3207 3208 3209 3210
    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
3211
    //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX;
3212
  } else {
3213
    openair_daq_vars.timing_advance = 0;
3214

3215 3216 3217 3218
    if (setup_eNB_buffers(PHY_vars_eNB_g[0],&openair0_cfg[0],rf_map)!=0) {
      printf("Error setting up eNB buffer\n");
      exit(-1);
    }
3219

3220
    printf("Setting eNB buffer to all-RX\n");
3221

3222
    // Set LSBs for antenna switch (ExpressMIMO)
3223
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3224
      for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++)
3225 3226
        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
3227
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3228
  }
3229

3230
#ifdef EXMIMO
3231
  openair0_config(&openair0_cfg[0],UE_flag);
Raymond Knopp's avatar
 
Raymond Knopp committed
3232 3233
#endif

3234
  /*
Raymond Knopp's avatar
 
Raymond Knopp committed
3235 3236
      for (ant=0;ant<4;ant++)
      p_exmimo_config->rf.do_autocal[ant] = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3237
  */
3238 3239

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3242 3243 3244 3245 3246 3247
  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);
3248
  else
Raymond Knopp's avatar
 
Raymond Knopp committed
3249
    printf("[OPENAIR][SCHED][INIT] Problem creating EMOS FIFO %d, error_code %d\n",CHANSOUNDER_FIFO_MINOR,error_code);
3250

3251 3252
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3253
  mlockall(MCL_CURRENT | MCL_FUTURE);
3254 3255

#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3256
  // make main thread LXRT soft realtime
3257
  /* task = */ rt_task_init_schmod(nam2num("MAIN"), 9, 0, 0, SCHED_FIFO, 0xF);
Raymond Knopp's avatar
 
Raymond Knopp committed
3258 3259 3260 3261 3262

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3265 3266
  pthread_cond_init(&sync_cond,NULL);
  pthread_mutex_init(&sync_mutex, NULL);
3267

3268
  /*  this is moved to the eNB main thread */ 
3269

3270
//#if defined(ENABLE_ITTI)
Florian Kaltenberger's avatar
Florian Kaltenberger committed
3271
  // Wait for eNB application initialization to be complete (eNB registration to MME)
3272 3273 3274 3275 3276
  //  if (UE_flag==0) {
  // printf("Waiting for eNB application to be ready\n");
    //wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB);
  // }
  //#endif
3277

Raymond Knopp's avatar
 
Raymond Knopp committed
3278 3279

  // this starts the DMA transfers
3280
#ifdef EXMIMO
3281

Raymond Knopp's avatar
 
Raymond Knopp committed
3282
  if (UE_flag!=1)
3283
    for (card=0; card<openair0_num_detected_cards; card++)
3284
      openair0_start_rt_acquisition(card);
3285

Raymond Knopp's avatar
 
Raymond Knopp committed
3286
#endif
3287 3288

#ifdef XFORMS
3289 3290
  int UE_id;

Raymond Knopp's avatar
 
Raymond Knopp committed
3291 3292
  if (do_forms==1) {
    fl_initialize (&argc, argv, NULL, 0, 0);
3293 3294

    if (UE_flag==0) {
3295
      form_stats_l2 = create_form_stats_form();
3296 3297 3298
      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");
3299 3300

      for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313
	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");
	  }
	}
3314
      }
3315
    } else {
3316 3317 3318 3319 3320 3321 3322
      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
3323
      if (openair_daq_vars.use_ia_receiver) {
3324 3325 3326 3327 3328
        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
3329 3330 3331
      }
    }

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

3334 3335
    if (ret == 0)
      pthread_setname_np( forms_thread, "xforms" );
3336

Raymond Knopp's avatar
 
Raymond Knopp committed
3337 3338
    printf("Scope thread created, ret=%d\n",ret);
  }
3339

3340 3341 3342
#endif

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3343 3344
  ret = pthread_create(&thread3, NULL, emos_thread, NULL);
  printf("EMOS thread created, ret=%d\n",ret);
jiangx's avatar
jiangx committed
3345 3346
  ret = pthread_create(&thread4, NULL, gps_thread, NULL);
  printf("GPS thread created, ret=%d\n",ret);
3347 3348
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3349
  rt_sleep_ns(10*FRAME_PERIOD);
3350 3351

#ifndef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3352
  pthread_attr_init (&attr_dlsch_threads);
3353
  pthread_attr_setstacksize(&attr_dlsch_threads,4*PTHREAD_STACK_MIN);
3354

3355
  pthread_attr_init (&attr_UE_thread);
3356
  pthread_attr_setstacksize(&attr_UE_thread,8192);//5*PTHREAD_STACK_MIN);
3357

3358
#ifndef LOWLATENCY
3359 3360
  sched_param_UE_thread.sched_priority = sched_get_priority_max(SCHED_FIFO);
  pthread_attr_setschedparam(&attr_UE_thread,&sched_param_UE_thread);
3361
  sched_param_dlsch.sched_priority = sched_get_priority_max(SCHED_FIFO); //OPENAIR_THREAD_PRIORITY;
Raymond Knopp's avatar
 
Raymond Knopp committed
3362 3363
  pthread_attr_setschedparam  (&attr_dlsch_threads, &sched_param_dlsch);
  pthread_attr_setschedpolicy (&attr_dlsch_threads, SCHED_FIFO);
3364
  printf("Setting eNB_thread FIFO scheduling policy with priority %d \n", sched_param_dlsch.sched_priority);
3365
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3366

3367 3368
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3369 3370
  // start the main thread
  if (UE_flag == 1) {
3371
    printf("Intializing UE Threads ...\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3372
    init_UE_threads();
3373 3374 3375 3376 3377
#ifdef DLSCH_THREAD
    init_rx_pdsch_thread();
    rt_sleep_ns(FRAME_PERIOD/10);
    init_dlsch_threads();
#endif
3378

3379
    sleep(1);
3380
#ifdef RTAI
3381
    main_ue_thread = rt_thread_create(UE_thread, NULL, 100000000);
3382
#else
3383
    error_code = pthread_create(&main_ue_thread, &attr_UE_thread, UE_thread, NULL);
3384

Raymond Knopp's avatar
 
Raymond Knopp committed
3385 3386 3387
    if (error_code!= 0) {
      LOG_D(HW,"[lte-softmodem.c] Could not allocate UE_thread, error %d\n",error_code);
      return(error_code);
3388
    } else {
3389 3390
      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
3391
    }
3392

3393
#endif
3394
    printf("UE threads created\n");
3395 3396 3397 3398 3399 3400 3401 3402 3403 3404
#ifdef USE_MME

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

#endif



3405
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
3406 3407
    if (multi_thread>0) {
      init_eNB_proc();
3408
      sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3409 3410
      LOG_D(HW,"[lte-softmodem.c] eNB threads created\n");
    }
3411

3412
    printf("Creating main eNB_thread \n");
Raymond Knopp's avatar
 
Raymond Knopp committed
3413
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3414
    main_eNB_thread = rt_thread_create(eNB_thread, NULL, PTHREAD_STACK_MIN);
Raymond Knopp's avatar
 
Raymond Knopp committed
3415
#else
3416
    error_code = pthread_create( &main_eNB_thread, &attr_dlsch_threads, eNB_thread, NULL );
3417

Raymond Knopp's avatar
 
Raymond Knopp committed
3418 3419 3420
    if (error_code!= 0) {
      LOG_D(HW,"[lte-softmodem.c] Could not allocate eNB_thread, error %d\n",error_code);
      return(error_code);
3421
    } else {
3422 3423
      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
3424
    }
3425

Raymond Knopp's avatar
 
Raymond Knopp committed
3426 3427
#endif
  }
3428

Raymond Knopp's avatar
 
Raymond Knopp committed
3429
  // Sleep to allow all threads to setup
Raymond Knopp's avatar
 
Raymond Knopp committed
3430
  sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3431

3432

3433

3434
#ifndef EXMIMO
3435

Raymond Knopp's avatar
 
Raymond Knopp committed
3436
#ifndef USRP_DEBUG
3437
  if (mode!=loop_through_memory)
navid's avatar
navid committed
3438 3439 3440
    if (openair0.trx_start_func(&openair0) != 0 ) 
      LOG_E(HW,"Could not start the device\n");

Raymond Knopp's avatar
 
Raymond Knopp committed
3441
#endif
3442

3443 3444
#endif

3445
  printf("Sending sync to all threads\n");
3446

Raymond Knopp's avatar
 
Raymond Knopp committed
3447
  pthread_mutex_lock(&sync_mutex);
3448
  sync_var=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3449 3450
  pthread_cond_broadcast(&sync_cond);
  pthread_mutex_unlock(&sync_mutex);
3451

Raymond Knopp's avatar
 
Raymond Knopp committed
3452 3453 3454
  // wait for end of program
  printf("TYPE <CTRL-C> TO TERMINATE\n");
  //getchar();
3455 3456

#if defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
3457 3458
  printf("Entering ITTI signals handler\n");
  itti_wait_tasks_end();
3459
  oai_exit=1;
3460
#else
3461

Raymond Knopp's avatar
 
Raymond Knopp committed
3462 3463
  while (oai_exit==0)
    rt_sleep_ns(FRAME_PERIOD);
3464

3465
#endif
3466

Raymond Knopp's avatar
 
Raymond Knopp committed
3467
  // stop threads
3468
#ifdef XFORMS
Raymond Knopp's avatar
 
Raymond Knopp committed
3469
  printf("waiting for XFORMS thread\n");
3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483

  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++) {
3484 3485 3486 3487
	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
3488
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
3489
    }
3490 3491
  }

3492 3493
#endif

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

Raymond Knopp's avatar
 
Raymond Knopp committed
3496 3497
  // cleanup
  if (UE_flag == 1) {
3498
#ifdef EXMIMO
3499
#ifdef RTAI
3500
    rt_thread_join(main_ue_thread);
3501
#else
3502
    pthread_join(main_ue_thread,&status);
3503 3504
#endif
#ifdef DLSCH_THREAD
Raymond Knopp's avatar
 
Raymond Knopp committed
3505 3506
    cleanup_dlsch_threads();
    cleanup_rx_pdsch_thread();
3507
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3508
#endif
3509
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
3510
#ifdef DEBUG_THREADS
Raymond Knopp's avatar
 
Raymond Knopp committed
3511
    printf("Joining eNB_thread ...");
Raymond Knopp's avatar
 
Raymond Knopp committed
3512
#endif
3513
#ifdef RTAI
3514
    rt_thread_join(main_eNB_thread);
3515
#else
3516 3517
    int *eNB_thread_status_p;
    int result = pthread_join( main_eNB_thread, (void**)&eNB_thread_status_p );
Raymond Knopp's avatar
 
Raymond Knopp committed
3518
#ifdef DEBUG_THREADS
3519

3520
    if (result != 0) {
3521
      printf( "\nError joining main_eNB_thread.\n" );
3522
    } else {
3523 3524 3525 3526 3527
      if (eNB_thread_status_p) {
        printf( "status %d\n", *eNB_thread_status_p );
      } else {
        printf( "The thread was killed. No status available.\n");
      }
3528
    }
3529

3530 3531
#else
    UNUSED(result);
3532 3533
#endif // DEBUG_THREADS
#endif // RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3534

Raymond Knopp's avatar
 
Raymond Knopp committed
3535 3536 3537
    if (multi_thread>0) {
      printf("Killing eNB processing threads\n");
      kill_eNB_proc();
Raymond Knopp's avatar
 
Raymond Knopp committed
3538
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3539
  }
3540

3541
#ifdef OPENAIR2
Raymond Knopp's avatar
 
Raymond Knopp committed
3542
  //cleanup_pdcp_thread();
3543 3544
#endif

3545
#ifdef RTAI
Raymond Knopp's avatar
 
Raymond Knopp committed
3546
  stop_rt_timer();
3547
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3548 3549
  pthread_cond_destroy(&sync_cond);
  pthread_mutex_destroy(&sync_mutex);
3550

3551

3552
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3553
  printf("stopping card\n");
3554
  openair0_stop(0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3555 3556
  printf("closing openair0_lib\n");
  openair0_close();
navid's avatar
navid committed
3557 3558
#else
  openair0.trx_end_func(&openair0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3559
#endif
3560 3561

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3562 3563 3564
  printf("waiting for EMOS thread\n");
  pthread_cancel(thread3);
  pthread_join(thread3,&status);
jiangx's avatar
jiangx committed
3565 3566 3567
  printf("waiting for GPS thread\n");
  pthread_cancel(thread4);
  pthread_join(thread4,&status);
3568 3569 3570
#endif

#ifdef EMOS
Raymond Knopp's avatar
 
Raymond Knopp committed
3571 3572
  error_code = rtf_destroy(CHANSOUNDER_FIFO_MINOR);
  printf("[OPENAIR][SCHED][CLEANUP] EMOS FIFO closed, error_code %d\n", error_code);
3573 3574
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3575
  if (ouput_vcd)
3576
    VCD_SIGNAL_DUMPER_CLOSE();
3577

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3578
#ifdef OPENAIR2
3579

3580
  if (opt_enabled == 1)
3581
    terminate_opt();
3582

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
3583
#endif
3584

Raymond Knopp's avatar
 
Raymond Knopp committed
3585
  logClean();
3586

Raymond Knopp's avatar
 
Raymond Knopp committed
3587 3588
  return 0;
}
3589 3590


3591 3592 3593
/* 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
3594
   antennas are mapped to successive RF chains on the same card. */
3595 3596
int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs])
{
3597

3598
  int i, CC_id;
3599
#ifndef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3600
  uint16_t N_TA_offset = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
3601 3602
#else
  int j;
Raymond Knopp's avatar
 
Raymond Knopp committed
3603
#endif
3604
  LTE_DL_FRAME_PARMS *frame_parms;
3605

Raymond Knopp's avatar
 
Raymond Knopp committed
3606

3607 3608
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    if (phy_vars_eNB[CC_id]) {
Raymond Knopp's avatar
 
Raymond Knopp committed
3609 3610
      frame_parms = &(phy_vars_eNB[CC_id]->lte_frame_parms);
      printf("setup_eNB_buffers: frame_parms = %p\n",frame_parms);
3611
    } else {
3612 3613
      printf("phy_vars_eNB[%d] not initialized\n", CC_id);
      return(-1);
Raymond Knopp's avatar
 
Raymond Knopp committed
3614
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3615

3616
#ifndef EXMIMO
3617

3618 3619
    if (frame_parms->frame_type == TDD) {
      if (frame_parms->N_RB_DL == 100)
3620
        N_TA_offset = 624;
3621
      else if (frame_parms->N_RB_DL == 50)
3622
        N_TA_offset = 624/2;
3623
      else if (frame_parms->N_RB_DL == 25)
3624
        N_TA_offset = 624/4;
Raymond Knopp's avatar
 
Raymond Knopp committed
3625
    }
3626

Raymond Knopp's avatar
 
Raymond Knopp committed
3627
#endif
3628

Raymond Knopp's avatar
 
Raymond Knopp committed
3629
    // replace RX signal buffers with mmaped HW versions
3630
#ifdef EXMIMO
Raymond Knopp's avatar
 
Raymond Knopp committed
3631 3632 3633
    openair0_cfg[CC_id].tx_num_channels = 0;
    openair0_cfg[CC_id].rx_num_channels = 0;

3634
    for (i=0; i<frame_parms->nb_antennas_rx; i++) {
3635 3636 3637
      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];
3638

3639
      if (openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i]) {
3640 3641 3642 3643 3644 3645
        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++;
3646
      }
3647

3648
      printf("rxdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]);
3649 3650 3651 3652

      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;
3653
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
3654
    }
3655 3656

    for (i=0; i<frame_parms->nb_antennas_tx; i++) {
3657 3658 3659
      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];
3660

3661
      if (openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i]) {
3662 3663 3664 3665 3666 3667
        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++;
3668
      }
3669

3670
      printf("txdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3671 3672 3673 3674

      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;
3675
      }
3676
    }
3677

3678
#else // not EXMIMO
3679 3680 3681
    rxdata = (int32_t**)malloc16(frame_parms->nb_antennas_rx*sizeof(int32_t*));
    txdata = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*));

3682
    for (i=0; i<frame_parms->nb_antennas_rx; i++) {
3683
      free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]);
3684
      rxdata[i] = (int32_t*)(32 + malloc16(32+openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation
3685
      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
3686
      memset(rxdata[i], 0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t));
3687
      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);
3688
      
Raymond Knopp's avatar
 
Raymond Knopp committed
3689
    }
3690 3691

    for (i=0; i<frame_parms->nb_antennas_tx; i++) {
3692
      free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3693
      txdata[i] = (int32_t*)(32 + malloc16(32 + openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation
3694
      phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i] = txdata[i];
3695
      memset(txdata[i],0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t));
3696
      printf("txdata[%d] @ %p\n", i, phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]);
3697

Raymond Knopp's avatar
 
Raymond Knopp committed
3698
    }
3699

Raymond Knopp's avatar
 
Raymond Knopp committed
3700
#endif
3701
  }
3702

3703
  return(0);
Raymond Knopp's avatar
 
Raymond Knopp committed
3704
}
3705

3706
void reset_opp_meas(void) {
3707 3708 3709
  int sfn;
  reset_meas(&softmodem_stats_mt);
  reset_meas(&softmodem_stats_hw);
3710
  
3711 3712 3713 3714 3715 3716
  for (sfn=0; sfn < 10; sfn++) {
    reset_meas(&softmodem_stats_tx_sf[sfn]);
    reset_meas(&softmodem_stats_rx_sf[sfn]);
  }
}

3717 3718
void print_opp_meas(void) {

3719 3720 3721
  int sfn=0;
  print_meas(&softmodem_stats_mt, "Main ENB Thread", NULL, NULL);
  print_meas(&softmodem_stats_hw, "HW Acquisation", NULL, NULL);
3722
  
3723 3724 3725 3726 3727
  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);
  }
}
3728 3729