lte-softmodem.c 40.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.0  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

22 23
/*! \file lte-enb.c
 * \brief Top-level threads for eNodeB
24
 * \author R. Knopp, F. Kaltenberger, Navid Nikaein
knopp's avatar
 
knopp committed
25 26 27
 * \date 2012
 * \version 0.1
 * \company Eurecom
28
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr
knopp's avatar
 
knopp committed
29 30 31
 * \note
 * \warning
 */
32

33

34

35 36
#include "T.h"

37
#include "rt_wrapper.h"
38

39

40 41
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all

42
#include "assertions.h"
43
#include "msc.h"
44 45

#include "PHY/types.h"
46

47
#include "PHY/defs.h"
48
#include "common/ran_context.h"
49
#include "common/config/config_userapi.h"
50

51
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
knopp's avatar
 
knopp committed
52
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
53

knopp's avatar
 
knopp committed
54
#include "../../ARCH/COMMON/common_lib.h"
55
#include "../../ARCH/ETHERNET/USERSPACE/LIB/if_defs.h"
knopp's avatar
 
knopp committed
56

knopp's avatar
 
knopp committed
57
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
58 59 60 61 62 63 64 65 66

#include "PHY/vars.h"
#include "SCHED/vars.h"
#include "LAYER2/MAC/vars.h"

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

#include "LAYER2/MAC/defs.h"
#include "LAYER2/MAC/vars.h"
67
#include "LAYER2/MAC/proto.h"
68 69 70 71 72 73 74 75
#include "RRC/LITE/vars.h"
#include "PHY_INTERFACE/vars.h"

#ifdef SMBV
#include "PHY/TOOLS/smbv.h"
unsigned short config_frames[4] = {2,9,11,13};
#endif
#include "UTIL/LOG/log_extern.h"
nikaeinn's avatar
nikaeinn committed
76
#include "UTIL/OTG/otg_tx.h"
77
#include "UTIL/OTG/otg_externs.h"
78 79
#include "UTIL/MATH/oml.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
80
#include "UTIL/OPT/opt.h"
81
#include "enb_config.h"
nikaeinn's avatar
nikaeinn committed
82
//#include "PHY/TOOLS/time_meas.h"
83

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
84 85 86 87
#ifndef OPENAIR2
#include "UTIL/OTG/otg_vars.h"
#endif

88
#if defined(ENABLE_ITTI)
89 90
#include "intertask_interface_init.h"
#include "create_tasks.h"
91 92
#endif

93 94
#include "system.h"

95 96 97
#ifdef XFORMS
#include "PHY/TOOLS/lte_phy_scope.h"
#include "stats.h"
98
#endif
99
#include "lte-softmodem.h"
100

101

102
#ifdef XFORMS
103
// current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0)
gauthier's avatar
gauthier committed
104
// at eNB 0, an UL scope for every UE
105
FD_lte_phy_scope_ue  *form_ue[NUMBER_OF_UE_MAX];
106
FD_lte_phy_scope_enb *form_enb[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
107
FD_stats_form                  *form_stats=NULL,*form_stats_l2=NULL;
108
char title[255];
109
unsigned char                   scope_enb_num_ue = 2;
110
static pthread_t                forms_thread; //xforms
111 112
#endif //XFORMS

knopp's avatar
 
knopp committed
113 114
pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex;
115
int sync_var=-1; //!< protected by mutex \ref sync_mutex.
116

117 118
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]
knopp's avatar
 
knopp committed
119

120
#if defined(ENABLE_ITTI)
121 122
volatile int             start_eNB = 0;
volatile int             start_UE = 0;
123
#endif
knopp's avatar
knopp committed
124
volatile int             oai_exit = 0;
125

126
static clock_source_t clock_source = internal;
127
static int wait_for_sync = 0;
knopp's avatar
 
knopp committed
128

knopp's avatar
knopp committed
129
static char              UE_flag=0;
130
unsigned int                    mmapped_dma=0;
131
int                             single_thread_flag=1;
132

133
static char                     threequarter_fs=0;
134

135
uint32_t                 downlink_frequency[MAX_NUM_CCs][4];
136
int32_t                  uplink_frequency_offset[MAX_NUM_CCs][4];
gauthier's avatar
gauthier committed
137

138

oai's avatar
oai committed
139

140
#if defined(ENABLE_ITTI)
141
static char                    *itti_dump_file = NULL;
knopp's avatar
 
knopp committed
142 143
#endif

144
int UE_scan = 1;
145
int UE_scan_carrier = 0;
146 147
runmode_t mode = normal_txrx;

148 149
FILE *input_fd=NULL;

150

151 152
#if MAX_NUM_CCs == 1
rx_gain_t                rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain}};
kortke's avatar
kortke committed
153 154
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0}};
155 156 157 158
#else
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}};
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0},{20,0,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0},{20,0,0,0}};
gauthier's avatar
gauthier committed
159
#endif
knopp's avatar
 
knopp committed
160

fnabet's avatar
fnabet committed
161
double rx_gain_off = 0.0;
162

knopp's avatar
 
knopp committed
163
double sample_rate=30.72e6;
164
double bw = 10.0e6;
165

166
static int                      tx_max_power[MAX_NUM_CCs]; /* =  {0,0}*/;
167

168 169
char   rf_config_file[1024];

Florian Kaltenberger's avatar
Florian Kaltenberger committed
170
int chain_offset=0;
171
int phy_test = 0;
172
uint8_t usim_test = 0;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
173

174 175 176
uint8_t dci_Format = 0;
uint8_t agregation_Level =0xFF;

177 178
uint8_t nb_antenna_tx = 1;
uint8_t nb_antenna_rx = 1;
179

knopp's avatar
 
knopp committed
180 181 182
char ref[128] = "internal";
char channels[128] = "0";

183
int                      rx_input_level_dBm;
184
static int                      online_log_messages=0;
185
#ifdef XFORMS
186
extern int                      otg_enabled;
187
static char                     do_forms=0;
188
#else
189
int                             otg_enabled;
190
#endif
knopp's avatar
 
knopp committed
191
//int                             number_of_cards =   1;
192

193 194

static LTE_DL_FRAME_PARMS      *frame_parms[MAX_NUM_CCs];
Florian Kaltenberger's avatar
Florian Kaltenberger committed
195
uint32_t target_dl_mcs = 28; //maximum allowed mcs
196
uint32_t target_ul_mcs = 20;
197
uint32_t timing_advance = 0;
198 199
uint8_t exit_missed_slots=1;
uint64_t num_missed_slots=0; // counter for the number of missed slots
200

201

202 203
extern void reset_opp_meas(void);
extern void print_opp_meas(void);
204

205
int transmission_mode=1;
knopp's avatar
 
knopp committed
206

207
int16_t           glog_level         = LOG_INFO;
gauthier's avatar
 
gauthier committed
208
int16_t           glog_verbosity     = LOG_MED;
209
int16_t           hw_log_level       = LOG_INFO;
gauthier's avatar
 
gauthier committed
210
int16_t           hw_log_verbosity   = LOG_MED;
211
int16_t           phy_log_level      = LOG_DEBUG;
gauthier's avatar
 
gauthier committed
212
int16_t           phy_log_verbosity  = LOG_MED;
213
int16_t           mac_log_level      = LOG_DEBUG;
gauthier's avatar
 
gauthier committed
214
int16_t           mac_log_verbosity  = LOG_MED;
215
int16_t           rlc_log_level      = LOG_INFO;
gauthier's avatar
 
gauthier committed
216
int16_t           rlc_log_verbosity  = LOG_MED;
217
int16_t           pdcp_log_level     = LOG_INFO;
gauthier's avatar
 
gauthier committed
218
int16_t           pdcp_log_verbosity = LOG_MED;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
219
int16_t           rrc_log_level      = LOG_INFO;
gauthier's avatar
 
gauthier committed
220
int16_t           rrc_log_verbosity  = LOG_MED;
221 222 223
int16_t           opt_log_level      = LOG_INFO;
int16_t           opt_log_verbosity  = LOG_MED;

gauthier's avatar
 
gauthier committed
224 225 226 227 228 229
# 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
230 231 232
#if defined (ENABLE_SECURITY)
int16_t           osa_log_level      = LOG_INFO;
int16_t           osa_log_verbosity  = LOG_MED;
233
#endif
234

235 236 237
/* struct for ethernet specific parameters given in eNB conf file */
eth_params_t *eth_params;

238 239 240 241
openair0_config_t openair0_cfg[MAX_CARDS];

double cpuf;

242 243
extern char uecap_xer[1024];
char uecap_xer_in=0;
244

245
int oaisim_flag=0;
246
threads_t threads= {-1,-1,-1,-1,-1,-1,-1};
knopp's avatar
 
knopp committed
247

Cedric Roux's avatar
Cedric Roux committed
248 249 250 251
/* see file openair2/LAYER2/MAC/main.c for why abstraction_flag is needed
 * this is very hackish - find a proper solution
 */
uint8_t abstraction_flag=0;
knopp's avatar
 
knopp committed
252

253 254 255 256 257
/*---------------------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 };

258
struct timespec clock_difftime(struct timespec start, struct timespec end) {
259 260 261 262 263 264 265 266 267
  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;
268 269
}

270
void print_difftimes(void) {
271
#ifdef DEBUG
272
  printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
273
#else
274
  LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
275 276 277
#endif
}

278
void update_difftimes(struct timespec start, struct timespec end) {
279 280 281
  struct timespec diff_time = { .tv_sec = 0, .tv_nsec = 0 };
  int             changed = 0;
  diff_time = clock_difftime(start, end);
282 283 284 285 286 287 288 289
  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;
  }
290
#if 1
291
  if (changed) print_difftimes();
292 293 294 295 296
#endif
}

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

297
unsigned int build_rflocal(int txi, int txq, int rxi, int rxq) {
knopp's avatar
 
knopp committed
298
  return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
299
}
300
unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe) {
knopp's avatar
 
knopp committed
301
  return (dcoff_i_rxfe + (dcoff_q_rxfe<<8));
302 303
}

304
#if !defined(ENABLE_ITTI)
305
void signal_handler(int sig) {
306 307 308 309 310 311
  void *array[10];
  size_t size;

  if (sig==SIGSEGV) {
    // get void*'s for all entries on the stack
    size = backtrace(array, 10);
312

313 314 315 316
    // print out all the frames to stderr
    fprintf(stderr, "Error: signal %d:\n", sig);
    backtrace_symbols_fd(array, size, 2);
    exit(-1);
317 318
  } else {
    printf("trying to exit gracefully...\n");
319
    oai_exit = 1;
320 321
  }
}
322
#endif
nikaeinn's avatar
nikaeinn committed
323 324 325 326 327 328
#define KNRM  "\x1B[0m"
#define KRED  "\x1B[31m"
#define KGRN  "\x1B[32m"
#define KBLU  "\x1B[34m"
#define RESET "\033[0m"

329

Raymond Knopp's avatar
Raymond Knopp committed
330

331 332
void exit_fun(const char* s)
{
Raymond Knopp's avatar
Raymond Knopp committed
333
  int CC_id;
334
  int ru_id;
Raymond Knopp's avatar
Raymond Knopp committed
335

336
  if (s != NULL) {
337
    printf("%s %s() Exiting OAI softmodem: %s\n",__FILE__, __FUNCTION__, s);
338 339 340
  }

  oai_exit = 1;
341 342 343 344 345 346 347 348 349 350

  if (UE_flag==0) {
    for (ru_id=0; ru_id<RC.nb_RU;ru_id++) {
      if (RC.ru[ru_id]->rfdevice.trx_end_func)
	RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice);
      if (RC.ru[ru_id]->ifdevice.trx_end_func)
	RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice);  
    }
  }

Raymond Knopp's avatar
Raymond Knopp committed
351
  for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
352 353 354 355

    oai_exit = 1;

    for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
356 357 358 359 360
      if (UE_flag == 0) {
      } else {
	if (PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func)
	  PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_UE_g[0][CC_id]->rfdevice);
      }
knopp's avatar
knopp committed
361
    }
362 363

#if defined(ENABLE_ITTI)
364 365
    sleep(1); //allow lte-softmodem threads to exit first
    itti_terminate_tasks (TASK_UNKNOWN);
366
#endif
367

368
  }
369

370
}
371

372
#ifdef XFORMS
373

374

375 376
void reset_stats(FL_OBJECT *button, long arg)
{
377
  int i,j,k;
378
  PHY_VARS_eNB *phy_vars_eNB = RC.eNB[0][0];
379 380 381

  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    for (k=0; k<8; k++) { //harq_processes
382
      for (j=0; j<phy_vars_eNB->dlsch[i][0]->Mlimit; j++) {
383 384 385
	phy_vars_eNB->UE_stats[i].dlsch_NAK[k][j]=0;
	phy_vars_eNB->UE_stats[i].dlsch_ACK[k][j]=0;
	phy_vars_eNB->UE_stats[i].dlsch_trials[k][j]=0;
386
      }
387

388 389 390
      phy_vars_eNB->UE_stats[i].dlsch_l2_errors[k]=0;
      phy_vars_eNB->UE_stats[i].ulsch_errors[k]=0;
      phy_vars_eNB->UE_stats[i].ulsch_consecutive_errors=0;
391 392


393 394 395
      phy_vars_eNB->UE_stats[i].dlsch_sliding_cnt=0;
      phy_vars_eNB->UE_stats[i].dlsch_NAK_round0=0;
      phy_vars_eNB->UE_stats[i].dlsch_mcs_offset=0;
396 397 398 399
    }
  }
}

400
static void *scope_thread(void *arg) {
knopp's avatar
 
knopp committed
401
  char stats_buffer[16384];
402
# ifdef ENABLE_XFORMS_WRITE_STATS
knopp's avatar
 
knopp committed
403
  FILE *UE_stats, *eNB_stats;
404
# endif
knopp's avatar
 
knopp committed
405
  struct sched_param sched_param;
406
  int UE_id, CC_id;
407
  int ue_cnt=0;
408

409
  sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
knopp's avatar
 
knopp committed
410
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
411

knopp's avatar
 
knopp committed
412
  printf("Scope thread has priority %d\n",sched_param.sched_priority);
413

414
# ifdef ENABLE_XFORMS_WRITE_STATS
415 416

  if (UE_flag==1)
knopp's avatar
 
knopp committed
417
    UE_stats  = fopen("UE_stats.txt", "w");
418
  else
knopp's avatar
 
knopp committed
419
    eNB_stats = fopen("eNB_stats.txt", "w");
420

421
#endif
422

knopp's avatar
 
knopp committed
423 424
  while (!oai_exit) {
    if (UE_flag==1) {
oai's avatar
oai committed
425
      dump_ue_stats (PHY_vars_UE_g[0][0], &PHY_vars_UE_g[0][0]->proc.proc_rxtx[0],stats_buffer, 0, mode,rx_input_level_dBm);
knopp's avatar
knopp committed
426 427 428
      //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);
429

430
      phy_scope_UE(form_ue[0],
431 432 433 434
		   PHY_vars_UE_g[0][0],
		   0,
		   0,7);

435

knopp's avatar
 
knopp committed
436
    } else {
437
      /*
438
	if (RC.eNB[0][0]->mac_enabled==1) {
439 440 441 442
	len = dump_eNB_l2_stats (stats_buffer, 0);
	//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);
443 444
	}
	len = dump_eNB_stats (RC.eNB[0][0], stats_buffer, 0);
445

446 447
	if (MAX_NUM_CCs>1)
	len += dump_eNB_stats (RC.eNB[0][1], &stats_buffer[len], 0);
448

449 450 451
	//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);
452
      */
453 454
      ue_cnt=0;
      for(UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
455
	for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
456
	  //	  if ((RC.eNB[0][CC_id]->dlsch[UE_id][0]->rnti>0) && (ue_cnt<scope_enb_num_ue)) {
457
	  if ((ue_cnt<scope_enb_num_ue)) {
gauthier's avatar
gauthier committed
458
	    phy_scope_eNB(form_enb[CC_id][ue_cnt],
459
			  RC.eNB[0][CC_id],
460 461 462
			  UE_id);
	    ue_cnt++;
	  }
463
	}
knopp's avatar
 
knopp committed
464
      }
465

466
    }
467
	
knopp's avatar
 
knopp committed
468
    //printf("doing forms\n");
Florian Kaltenberger's avatar
Florian Kaltenberger committed
469 470
    //usleep(100000); // 100 ms
    sleep(1);
knopp's avatar
 
knopp committed
471
  }
472

473
  //  printf("%s",stats_buffer);
474

475
# ifdef ENABLE_XFORMS_WRITE_STATS
476

477 478 479 480 481 482
  if (UE_flag==1) {
    if (UE_stats) {
      rewind (UE_stats);
      fwrite (stats_buffer, 1, len, UE_stats);
      fclose (UE_stats);
    }
483
  } else {
484 485 486 487 488 489
    if (eNB_stats) {
      rewind (eNB_stats);
      fwrite (stats_buffer, 1, len, eNB_stats);
      fclose (eNB_stats);
    }
  }
490

491
# endif
492

knopp's avatar
 
knopp committed
493
  pthread_exit((void*)arg);
494 495 496
}
#endif

497

498

499

knopp's avatar
 
knopp committed
500
#if defined(ENABLE_ITTI)
501
void *l2l1_task(void *arg) {
knopp's avatar
 
knopp committed
502 503 504 505 506
  MessageDef *message_p = NULL;
  int         result;

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
507

knopp's avatar
 
knopp committed
508 509
  if (UE_flag == 0) {
    /* Wait for the initialize message */
510
    printf("Wait for the ITTI initialize message\n");
511
    do {
knopp's avatar
 
knopp committed
512
      if (message_p != NULL) {
513 514
	result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
	AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
knopp's avatar
 
knopp committed
515
      }
516

517 518 519
      itti_receive_msg (TASK_L2L1, &message_p);

      switch (ITTI_MSG_ID(message_p)) {
knopp's avatar
 
knopp committed
520
      case INITIALIZE_MESSAGE:
521 522 523 524
	/* Start eNB thread */
	LOG_D(EMU, "L2L1 TASK received %s\n", ITTI_MSG_NAME(message_p));
	start_eNB = 1;
	break;
knopp's avatar
 
knopp committed
525 526

      case TERMINATE_MESSAGE:
527 528 529 530
	printf("received terminate message\n");
	oai_exit=1;
	itti_exit_task ();
	break;
knopp's avatar
 
knopp committed
531 532

      default:
533 534
	LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
	break;
535
      }
knopp's avatar
 
knopp committed
536
    } while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE);
537

knopp's avatar
 
knopp committed
538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558
    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;
559

knopp's avatar
 
knopp committed
560 561 562 563 564 565 566 567 568 569 570
    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);
thomasl's avatar
thomasl committed
571
  } while(!oai_exit);
572

knopp's avatar
 
knopp committed
573
  return NULL;
574 575 576
}
#endif

577

578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599
static void get_options(void) {
  int CC_id;
  int tddflag;
  char *loopfile=NULL;
  int dumpframe;
  paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC ;

  config_process_cmdline( cmdline_params,sizeof(cmdline_params)/sizeof(paramdef_t),NULL); 

  if (strlen(in_path) > 0) {
      opt_type = OPT_PCAP;
      opt_enabled=1;
      printf("Enabling OPT for PCAP  with the following file %s \n",in_path);
  }
  if (strlen(in_ip) > 0) {
      opt_enabled=1;
      opt_type = OPT_WIRESHARK;
      printf("Enabling OPT for wireshark for local interface");
  }
  if (UE_flag > 0) {
     paramdef_t cmdline_uemodeparams[] =CMDLINE_UEMODEPARAMS_DESC;
     paramdef_t cmdline_ueparams[] =CMDLINE_UEPARAMS_DESC;
oai's avatar
oai committed
600 601 602



603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628
     config_process_cmdline( cmdline_uemodeparams,sizeof(cmdline_uemodeparams)/sizeof(paramdef_t),NULL);
     config_process_cmdline( cmdline_ueparams,sizeof(cmdline_ueparams)/sizeof(paramdef_t),NULL);
      if (loopfile != NULL) {
  	  printf("Input file for hardware emulation: %s",loopfile);
  	  mode=loop_through_memory;
  	  input_fd = fopen(loopfile,"r");
  	  AssertFatal(input_fd != NULL,"Please provide a valid input file\n");
      }
      if ( (cmdline_uemodeparams[CMDLINE_CALIBUERX_IDX].paramflags &  PARAMFLAG_PARAMSET) != 0) mode = rx_calib_ue;
      if ( (cmdline_uemodeparams[CMDLINE_CALIBUERXMED_IDX].paramflags &  PARAMFLAG_PARAMSET) != 0) mode = rx_calib_ue_med;
      if ( (cmdline_uemodeparams[CMDLINE_CALIBUERXBYP_IDX].paramflags &  PARAMFLAG_PARAMSET) != 0) mode = rx_calib_ue_byp;
      if ( *(cmdline_uemodeparams[CMDLINE_DEBUGUEPRACH_IDX].uptr) > 0) mode = debug_prach;
      if ( *(cmdline_uemodeparams[CMDLINE_NOL2CONNECT_IDX].uptr) > 0)  mode = no_L2_connect;
      if ( *(cmdline_uemodeparams[CMDLINE_CALIBPRACHTX_IDX].uptr) > 0) mode = calib_prach_tx; 
      if (dumpframe  > 0)  mode = rx_dump_frame;
      
      if ( downlink_frequency[0][0] > 0) {
  	  for (CC_id=1; CC_id<MAX_NUM_CCs; CC_id++) {
  	    downlink_frequency[CC_id][1] = downlink_frequency[0][0];
  	    downlink_frequency[CC_id][2] = downlink_frequency[0][0];
  	    downlink_frequency[CC_id][3] = downlink_frequency[0][0];
  	    printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
  	  }
      UE_scan=0;
      } 

oai's avatar
oai committed
629 630 631 632
      if (tddflag > 0) {
         for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) 
	     frame_parms[CC_id]->frame_type = TDD;
      }
633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670

      if (frame_parms[0]->N_RB_DL !=0) {
  	  if ( frame_parms[0]->N_RB_DL < 6 ) {
  	     frame_parms[0]->N_RB_DL = 6;
  	     printf ( "%i: Invalid number of ressource blocks, adjusted to 6\n",frame_parms[0]->N_RB_DL);
  	  }
  	  if ( frame_parms[0]->N_RB_DL > 100 ) {
  	     frame_parms[0]->N_RB_DL = 100;
  	     printf ( "%i: Invalid number of ressource blocks, adjusted to 100\n",frame_parms[0]->N_RB_DL);
  	  }
  	  if ( frame_parms[0]->N_RB_DL > 50 && frame_parms[0]->N_RB_DL < 100 ) {
  	     frame_parms[0]->N_RB_DL = 50;
  	     printf ( "%i: Invalid number of ressource blocks, adjusted to 50\n",frame_parms[0]->N_RB_DL);
  	  }
  	  if ( frame_parms[0]->N_RB_DL > 25 && frame_parms[0]->N_RB_DL < 50 ) {
  	     frame_parms[0]->N_RB_DL = 25;
  	     printf ( "%i: Invalid number of ressource blocks, adjusted to 25\n",frame_parms[0]->N_RB_DL);
  	  }
  	  UE_scan = 0;
  	  frame_parms[0]->N_RB_UL=frame_parms[0]->N_RB_DL;
  	  for (CC_id=1; CC_id<MAX_NUM_CCs; CC_id++) {
  	      frame_parms[CC_id]->N_RB_DL=frame_parms[0]->N_RB_DL;
  	      frame_parms[CC_id]->N_RB_UL=frame_parms[0]->N_RB_UL;
  	  }
      }


      for (CC_id=1;CC_id<MAX_NUM_CCs;CC_id++) {
  	    tx_max_power[CC_id]=tx_max_power[0];
	    rx_gain[0][CC_id] = rx_gain[0][0];
	    tx_gain[0][CC_id] = tx_gain[0][0];
      }
  } /* UE_flag > 0 */
#if T_TRACER
  paramdef_t cmdline_ttraceparams[] =CMDLINE_TTRACEPARAMS_DESC ;
  config_process_cmdline( cmdline_ttraceparams,sizeof(cmdline_ttraceparams)/sizeof(paramdef_t),NULL);   
#endif

671 672 673 674
  if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT)) ) {
    if (UE_flag == 0) {
      memset((void*)&RC,0,sizeof(RC));
      /* Read RC configuration file */
675
      RCConfig();
676 677 678
      NB_eNB_INST = RC.nb_inst;
      NB_RU	  = RC.nb_RU;
      printf("Configuration: nb_inst %d, nb_ru %d\n",NB_eNB_INST,NB_RU);
679
    }
680 681 682 683 684 685
  } else if (UE_flag == 1 && (CONFIG_GETCONFFILE != NULL)) {
    // Here the configuration file is the XER encoded UE capabilities
    // Read it in and store in asn1c data structures
    strcpy(uecap_xer,CONFIG_GETCONFFILE);
    uecap_xer_in=1;
  } /* UE with config file  */
686 687 688
}


689
  
690 691 692
#if T_TRACER
int T_wait = 1;       /* by default we wait for the tracer */
int T_port = 2021;    /* default port to listen to to wait for the tracer */
693
int T_dont_fork = 0;  /* default is to fork, see 'T_init' to understand */
694 695
#endif

696

knopp's avatar
knopp committed
697 698
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
knopp's avatar
knopp committed
699 700 701 702 703 704 705 706 707 708 709 710 711 712 713

  int CC_id;

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    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 */
    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            = 0;
    frame_parms[CC_id]->num_MBSFN_config    = 0;
714
    frame_parms[CC_id]->nb_antenna_ports_eNB  = 1;
knopp's avatar
knopp committed
715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743
    frame_parms[CC_id]->nb_antennas_tx      = 1;
    frame_parms[CC_id]->nb_antennas_rx      = 1;

    frame_parms[CC_id]->nushift             = 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;

    frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22;
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1;
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0;
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.highSpeedFlag=0;
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_FreqOffset=0;

    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];
    //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);

  }

}

knopp's avatar
knopp committed
744 745
void init_openair0(void);

knopp's avatar
knopp committed
746 747 748 749 750 751 752 753 754 755 756 757 758
void init_openair0() {

  int card;
  int i;

  for (card=0; card<MAX_CARDS; card++) {

    openair0_cfg[card].mmapped_dma=mmapped_dma;
    openair0_cfg[card].configFilename = NULL;

    if(frame_parms[0]->N_RB_DL == 100) {
      if (frame_parms[0]->threequarter_fs) {
	openair0_cfg[card].sample_rate=23.04e6;
759
	openair0_cfg[card].samples_per_frame = 230400;
knopp's avatar
knopp committed
760 761
	openair0_cfg[card].tx_bw = 10e6;
	openair0_cfg[card].rx_bw = 10e6;
762
      } else {
knopp's avatar
knopp committed
763
	openair0_cfg[card].sample_rate=30.72e6;
764
	openair0_cfg[card].samples_per_frame = 307200;
knopp's avatar
knopp committed
765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793
	openair0_cfg[card].tx_bw = 10e6;
	openair0_cfg[card].rx_bw = 10e6;
      }
    } 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;
    }




    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;

    printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card,
794 795
	   ((UE_flag==0) ? RC.eNB[0][0]->frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx),
	   ((UE_flag==0) ? RC.eNB[0][0]->frame_parms.nb_antennas_rx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx));
knopp's avatar
knopp committed
796 797 798
    openair0_cfg[card].Mod_id = 0;

    openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL;
799

800
    openair0_cfg[card].clock_source = clock_source;
801

802

803 804
    openair0_cfg[card].tx_num_channels=min(2,((UE_flag==0) ? RC.eNB[0][0]->frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx));
    openair0_cfg[card].rx_num_channels=min(2,((UE_flag==0) ? RC.eNB[0][0]->frame_parms.nb_antennas_rx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx));
805

knopp's avatar
knopp committed
806
    for (i=0; i<4; i++) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
807

knopp's avatar
knopp committed
808 809 810 811
      if (i<openair0_cfg[card].tx_num_channels)
	openair0_cfg[card].tx_freq[i] = (UE_flag==0) ? downlink_frequency[0][i] : downlink_frequency[0][i]+uplink_frequency_offset[0][i];
      else
	openair0_cfg[card].tx_freq[i]=0.0;
812

knopp's avatar
knopp committed
813 814 815 816 817 818 819 820
      if (i<openair0_cfg[card].rx_num_channels)
	openair0_cfg[card].rx_freq[i] = (UE_flag==0) ? downlink_frequency[0][i] + uplink_frequency_offset[0][i] : downlink_frequency[0][i];
      else
	openair0_cfg[card].rx_freq[i]=0.0;

      openair0_cfg[card].autocal[i] = 1;
      openair0_cfg[card].tx_gain[i] = tx_gain[0][i];
      if (UE_flag == 0) {
821
	openair0_cfg[card].rx_gain[i] = RC.eNB[0][0]->rx_total_gain_dB;
knopp's avatar
knopp committed
822 823
      }
      else {
fnabet's avatar
fnabet committed
824
	openair0_cfg[card].rx_gain[i] = PHY_vars_UE_g[0][0]->rx_total_gain_dB - rx_gain_off;
knopp's avatar
knopp committed
825 826
      }

827
      openair0_cfg[card].configFilename = rf_config_file;
828
      printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n",
829 830 831 832
	     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]);
833
    }
knopp's avatar
 
knopp committed
834
  }
knopp's avatar
 
knopp committed
835
}
836

837

838
void wait_RUs(void) {
839 840 841 842 843 844 845 846 847 848 849 850 851 852 853

  LOG_I(PHY,"Waiting for RUs to be configured ...\n");

  // wait for all RUs to be configured over fronthaul
  pthread_mutex_lock(&RC.ru_mutex);



  while (RC.ru_mask>0) {
    pthread_cond_wait(&RC.ru_cond,&RC.ru_mutex);
  }

  LOG_I(PHY,"RUs configured\n");
}

854
void wait_eNBs(void) {
855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872

  int i,j;
  int waiting=1;


  while (waiting==1) {
    printf("Waiting for eNB L1 instances to all get configured ... sleeping 500ms (nb_L1_inst %d)\n",RC.nb_L1_inst);
    usleep(500000);
    waiting=0;
    for (i=0;i<RC.nb_L1_inst;i++)
      for (j=0;j<RC.nb_L1_CC[i];j++)
	if (RC.eNB[i][j]->configured==0) {
	  waiting=1;
	  break;
	}
  }
  printf("eNB L1 are configured\n");
}
873

874 875
int main( int argc, char **argv )
{
876
  int i;
877
#if defined (XFORMS)
knopp's avatar
 
knopp committed
878
  void *status;
879
#endif
880

knopp's avatar
 
knopp committed
881
  int CC_id;
882
  int ru_id;
knopp's avatar
knopp committed
883
  uint8_t  abstraction_flag=0;
knopp's avatar
 
knopp committed
884
  uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2;
885

knopp's avatar
 
knopp committed
886
#if defined (XFORMS)
887 888
  int ret;
#endif
889

890
  start_background_system();
891 892 893
  if ( load_configmodule(argc,argv) == NULL) {
    exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
  } 
894

895
      
896 897 898 899 900
#ifdef DEBUG_CONSOLE
  setvbuf(stdout, NULL, _IONBF, 0);
  setvbuf(stderr, NULL, _IONBF, 0);
#endif

901 902 903
  PHY_VARS_UE *UE[MAX_NUM_CCs];

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

906
  memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
907

knopp's avatar
 
knopp committed
908
  set_latency_target();
909 910


knopp's avatar
knopp committed
911
  // set default parameters
912
  if (UE_flag == 1) set_default_frame_parms(frame_parms);
913

914
  logInit();
knopp's avatar
knopp committed
915

916
  printf("Reading in command-line options\n");
917

918
  get_options ();