lte-softmodem.c 35.5 KB
Newer Older
1
2
3
4
5
/*
 * 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
Cedric Roux's avatar
Cedric Roux committed
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 * 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

Cedric Roux's avatar
Cedric Roux committed
34
35
36
#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include <sched.h>

37

38
39
#include "T.h"

40
#include "rt_wrapper.h"
41

42

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

45
#include "assertions.h"
46
#include "msc.h"
47
48

#include "PHY/types.h"
49

50
#include "PHY/defs.h"
51
#include "common/ran_context.h"
52
#include "common/config/config_userapi.h"
oai's avatar
oai committed
53
#include "common/utils/load_module_shlib.h"
54
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
knopp's avatar
   
knopp committed
55
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
56

knopp's avatar
   
knopp committed
57
#include "../../ARCH/COMMON/common_lib.h"
58
#include "../../ARCH/ETHERNET/USERSPACE/LIB/if_defs.h"
knopp's avatar
   
knopp committed
59

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

#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"
70
#include "LAYER2/MAC/proto.h"
71
72
73
74
75
76
77
78
#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
79
#include "UTIL/OTG/otg_tx.h"
80
#include "UTIL/OTG/otg_externs.h"
81
82
#include "UTIL/MATH/oml.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
83
#include "UTIL/OPT/opt.h"
84
#include "enb_config.h"
nikaeinn's avatar
nikaeinn committed
85
//#include "PHY/TOOLS/time_meas.h"
86

Florian Kaltenberger's avatar
   
Florian Kaltenberger committed
87
88
89
90
#ifndef OPENAIR2
#include "UTIL/OTG/otg_vars.h"
#endif

91
#if defined(ENABLE_ITTI)
92
93
#include "intertask_interface_init.h"
#include "create_tasks.h"
94
95
#endif

96
97
#include "system.h"

98
99
100
#ifdef XFORMS
#include "PHY/TOOLS/lte_phy_scope.h"
#include "stats.h"
101
#endif
102
#include "lte-softmodem.h"
103

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

115
116
117
118
119
120
pthread_cond_t nfapi_sync_cond;
pthread_mutex_t nfapi_sync_mutex;
int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex

uint8_t nfapi_mode = 0; // Default to monolithic mode

knopp's avatar
   
knopp committed
121
122
pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex;
123
int sync_var=-1; //!< protected by mutex \ref sync_mutex.
124
int config_sync_var=-1;
125

126
127
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
128

129
#if defined(ENABLE_ITTI)
130
131
volatile int             start_eNB = 0;
volatile int             start_UE = 0;
132
#endif
knopp's avatar
knopp committed
133
volatile int             oai_exit = 0;
134

135
static clock_source_t clock_source = internal;
136
static int wait_for_sync = 0;
knopp's avatar
   
knopp committed
137

138
unsigned int                    mmapped_dma=0;
139
int                             single_thread_flag=1;
140

141
static int8_t                     threequarter_fs=0;
142

143
uint32_t                 downlink_frequency[MAX_NUM_CCs][4];
144
int32_t                  uplink_frequency_offset[MAX_NUM_CCs][4];
gauthier's avatar
gauthier committed
145

146

oai's avatar
oai committed
147

148
#if defined(ENABLE_ITTI)
149
static char                    *itti_dump_file = NULL;
knopp's avatar
   
knopp committed
150
151
#endif

152
int UE_scan = 1;
153
int UE_scan_carrier = 0;
154
155
runmode_t mode = normal_txrx;

156
157
FILE *input_fd=NULL;

158

159
160
#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
161
162
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0}};
163
164
165
166
#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
167
#endif
knopp's avatar
   
knopp committed
168

fnabet's avatar
fnabet committed
169
double rx_gain_off = 0.0;
170

knopp's avatar
   
knopp committed
171
double sample_rate=30.72e6;
172
double bw = 10.0e6;
173

174
static int                      tx_max_power[MAX_NUM_CCs]; /* =  {0,0}*/;
175

176
177
char   rf_config_file[1024];

Florian Kaltenberger's avatar
Florian Kaltenberger committed
178
int chain_offset=0;
179
int phy_test = 0;
180
uint8_t usim_test = 0;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
181

182
183
184
uint8_t dci_Format = 0;
uint8_t agregation_Level =0xFF;

185
186
uint8_t nb_antenna_tx = 1;
uint8_t nb_antenna_rx = 1;
187

knopp's avatar
   
knopp committed
188
189
190
char ref[128] = "internal";
char channels[128] = "0";

191
int                      rx_input_level_dBm;
oai's avatar
oai committed
192

193
#ifdef XFORMS
194
extern int                      otg_enabled;
195
static char                     do_forms=0;
196
#else
197
int                             otg_enabled;
198
#endif
knopp's avatar
   
knopp committed
199
//int                             number_of_cards =   1;
200

201
202

static LTE_DL_FRAME_PARMS      *frame_parms[MAX_NUM_CCs];
Florian Kaltenberger's avatar
Florian Kaltenberger committed
203
uint32_t target_dl_mcs = 28; //maximum allowed mcs
204
uint32_t target_ul_mcs = 20;
205
uint32_t timing_advance = 0;
206
207
uint8_t exit_missed_slots=1;
uint64_t num_missed_slots=0; // counter for the number of missed slots
208

209

210
211
extern void reset_opp_meas(void);
extern void print_opp_meas(void);
212

213
214
215
216
217
218
extern PHY_VARS_UE* init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms,
			  uint8_t UE_id,
			  uint8_t abstraction_flag);

extern void init_eNB_afterRU(void);

219
int transmission_mode=1;
knopp's avatar
   
knopp committed
220

221

222

223
224
225
/* struct for ethernet specific parameters given in eNB conf file */
eth_params_t *eth_params;

226
227
228
229
openair0_config_t openair0_cfg[MAX_CARDS];

double cpuf;

230
231
extern char uecap_xer[1024];
char uecap_xer_in=0;
232

233
int oaisim_flag=0;
234
threads_t threads= {-1,-1,-1,-1,-1,-1,-1};
knopp's avatar
   
knopp committed
235

Cedric Roux's avatar
Cedric Roux committed
236
237
238
239
/* 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
240

241
242
243
/* forward declarations */
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);

244
245
246
247
248
/*---------------------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 };

249
struct timespec clock_difftime(struct timespec start, struct timespec end) {
250
251
252
253
254
255
256
257
258
  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;
259
260
}

261
void print_difftimes(void) {
262
#ifdef DEBUG
263
  printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
264
#else
265
  LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
266
267
268
#endif
}

269
void update_difftimes(struct timespec start, struct timespec end) {
270
271
272
  struct timespec diff_time = { .tv_sec = 0, .tv_nsec = 0 };
  int             changed = 0;
  diff_time = clock_difftime(start, end);
273
274
275
276
277
278
279
280
  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;
  }
281
#if 1
282
  if (changed) print_difftimes();
283
284
285
286
287
#endif
}

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

288
unsigned int build_rflocal(int txi, int txq, int rxi, int rxq) {
knopp's avatar
   
knopp committed
289
  return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
290
}
291
unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe) {
knopp's avatar
   
knopp committed
292
  return (dcoff_i_rxfe + (dcoff_q_rxfe<<8));
293
294
}

295
#if !defined(ENABLE_ITTI)
296
void signal_handler(int sig) {
297
298
299
300
301
302
  void *array[10];
  size_t size;

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

304
305
306
307
    // print out all the frames to stderr
    fprintf(stderr, "Error: signal %d:\n", sig);
    backtrace_symbols_fd(array, size, 2);
    exit(-1);
308
309
  } else {
    printf("trying to exit gracefully...\n");
310
    oai_exit = 1;
311
312
  }
}
313
#endif
nikaeinn's avatar
nikaeinn committed
314
315
316
317
318
319
#define KNRM  "\x1B[0m"
#define KRED  "\x1B[31m"
#define KGRN  "\x1B[32m"
#define KBLU  "\x1B[34m"
#define RESET "\033[0m"

320

Raymond Knopp's avatar
Raymond Knopp committed
321

322
323
void exit_fun(const char* s)
{
324

325
  int ru_id;
Raymond Knopp's avatar
Raymond Knopp committed
326

327
  if (s != NULL) {
328
    printf("%s %s() Exiting OAI softmodem: %s\n",__FILE__, __FUNCTION__, s);
329
330
331
  }

  oai_exit = 1;
332

333
334
335

    if (RC.ru == NULL)
        exit(-1); // likely init not completed, prevent crash or hang, exit now...
336
    for (ru_id=0; ru_id<RC.nb_RU;ru_id++) {
337
      if (RC.ru[ru_id] && RC.ru[ru_id]->rfdevice.trx_end_func)
338
	RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice);
339
      if (RC.ru[ru_id] && RC.ru[ru_id]->ifdevice.trx_end_func)
340
341
	RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice);  
    }
342

343
344

#if defined(ENABLE_ITTI)
345
346
    sleep(1); //allow lte-softmodem threads to exit first
    itti_terminate_tasks (TASK_UNKNOWN);
347
#endif
348
349


350
}
351

352
#ifdef XFORMS
353

354

355
356
void reset_stats(FL_OBJECT *button, long arg)
{
357
  int i,j,k;
358
  PHY_VARS_eNB *phy_vars_eNB = RC.eNB[0][0];
359
360
361

  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    for (k=0; k<8; k++) { //harq_processes
362
      for (j=0; j<phy_vars_eNB->dlsch[i][0]->Mlimit; j++) {
363
364
365
	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;
366
      }
367

368
369
370
      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;
371
372


373
374
375
      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;
376
377
378
379
    }
  }
}

380
static void *scope_thread(void *arg) {
381
 
382
# ifdef ENABLE_XFORMS_WRITE_STATS
383
  FILE *eNB_stats;
384
# endif
knopp's avatar
   
knopp committed
385
  struct sched_param sched_param;
386
  int UE_id, CC_id;
387
  int ue_cnt=0;
388

389
  sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
knopp's avatar
   
knopp committed
390
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
391

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

394
# ifdef ENABLE_XFORMS_WRITE_STATS
395

396
  eNB_stats = fopen("eNB_stats.txt", "w");
397

398
#endif
399

knopp's avatar
   
knopp committed
400
  while (!oai_exit) {
401

402
403
      ue_cnt=0;
      for(UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
404
	for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
405
	  if ((ue_cnt<scope_enb_num_ue)) {
gauthier's avatar
gauthier committed
406
	    phy_scope_eNB(form_enb[CC_id][ue_cnt],
407
			  RC.eNB[0][CC_id],
408
409
410
			  UE_id);
	    ue_cnt++;
	  }
411
	}
412
      }	
Florian Kaltenberger's avatar
Florian Kaltenberger committed
413
    sleep(1);
knopp's avatar
   
knopp committed
414
  }
415

416
  //  printf("%s",stats_buffer);
417

418
# ifdef ENABLE_XFORMS_WRITE_STATS
419

420
421
422
423
424
    if (eNB_stats) {
      rewind (eNB_stats);
      fwrite (stats_buffer, 1, len, eNB_stats);
      fclose (eNB_stats);
    }
425

426
# endif
427

knopp's avatar
   
knopp committed
428
  pthread_exit((void*)arg);
429
430
431
}
#endif

432

433

434

knopp's avatar
   
knopp committed
435
#if defined(ENABLE_ITTI)
436
void *l2l1_task(void *arg) {
knopp's avatar
   
knopp committed
437
438
439
440
441
  MessageDef *message_p = NULL;
  int         result;

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
442

knopp's avatar
   
knopp committed
443
    /* Wait for the initialize message */
444
    printf("Wait for the ITTI initialize message\n");
445
    do {
knopp's avatar
   
knopp committed
446
      if (message_p != NULL) {
447
448
	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
449
      }
450

451
452
453
      itti_receive_msg (TASK_L2L1, &message_p);

      switch (ITTI_MSG_ID(message_p)) {
knopp's avatar
   
knopp committed
454
      case INITIALIZE_MESSAGE:
455
456
457
458
	/* 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
459
460

      case TERMINATE_MESSAGE:
461
462
	printf("received terminate message\n");
	oai_exit=1;
463
        start_eNB = 0;
464
465
	itti_exit_task ();
	break;
knopp's avatar
   
knopp committed
466
467

      default:
468
469
	LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
	break;
470
      }
knopp's avatar
   
knopp committed
471
    } while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE);
472

knopp's avatar
   
knopp committed
473
474
    result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
475
/* ???? no else but seems to be UE only ??? 
knopp's avatar
   
knopp committed
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
  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;
493

knopp's avatar
   
knopp committed
494
495
496
497
498
499
500
501
502
503
504
    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
505
  } while(!oai_exit);
506
*/
knopp's avatar
   
knopp committed
507
  return NULL;
508
509
510
}
#endif

511

512
static void get_options(void) {
513
 
514
  int tddflag, nonbiotflag;
515
516
 
  
oai's avatar
oai committed
517
518
  uint32_t online_log_messages;
  uint32_t glog_level, glog_verbosity;
oai's avatar
oai committed
519
  uint32_t start_telnetsrv;
oai's avatar
oai committed
520

521
  paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC ;
oai's avatar
oai committed
522
  paramdef_t cmdline_logparams[] =CMDLINE_LOGPARAMS_DESC ;
523
524
525
526
527
528
529
530
531
532
533
534
535

  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");
  }
oai's avatar
oai committed
536
537
538
539
540
541
542
543

  config_process_cmdline( cmdline_logparams,sizeof(cmdline_logparams)/sizeof(paramdef_t),NULL);
  if(config_isparamset(cmdline_logparams,CMDLINE_ONLINELOG_IDX)) {
      set_glog_onlinelog(online_log_messages);
  }
  if(config_isparamset(cmdline_logparams,CMDLINE_GLOGLEVEL_IDX)) {
      set_glog(glog_level, -1);
  }
544
  if(config_isparamset(cmdline_logparams,CMDLINE_GLOGVERBO_IDX)) {
oai's avatar
oai committed
545
546
      set_glog(-1, glog_verbosity);
  }
oai's avatar
oai committed
547
  if (start_telnetsrv) {
548
     load_module_shlib("telnetsrv",NULL,0);
oai's avatar
oai committed
549
550
  }

551
552
553
554
555
#if T_TRACER
  paramdef_t cmdline_ttraceparams[] =CMDLINE_TTRACEPARAMS_DESC ;
  config_process_cmdline( cmdline_ttraceparams,sizeof(cmdline_ttraceparams)/sizeof(paramdef_t),NULL);   
#endif

556
557
558
  if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT)) ) {
      memset((void*)&RC,0,sizeof(RC));
      /* Read RC configuration file */
559
      RCConfig();
560
561
      NB_eNB_INST = RC.nb_inst;
      NB_RU	  = RC.nb_RU;
562
      printf("Configuration: nb_rrc_inst %d, nb_L1_inst %d, nb_ru %d\n",NB_eNB_INST,RC.nb_L1_inst,NB_RU);
563
   }
564
565
566
}


567
#if T_TRACER
Cedric Roux's avatar
Cedric Roux committed
568
int T_nowait = 0;     /* by default we wait for the tracer */
569
int T_port = 2021;    /* default port to listen to to wait for the tracer */
570
int T_dont_fork = 0;  /* default is to fork, see 'T_init' to understand */
571
572
#endif

573

574

knopp's avatar
knopp committed
575
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
knopp's avatar
knopp committed
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590

  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;
591
    frame_parms[CC_id]->nb_antenna_ports_eNB  = 1;
knopp's avatar
knopp committed
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
    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;

611
612
613
614
//    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];
knopp's avatar
knopp committed
615
    //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
616
    frame_parms[CC_id]->dl_CarrierFreq=downlink_frequency[CC_id][0];
oai's avatar
oai committed
617

knopp's avatar
knopp committed
618
619
620
621
  }

}

knopp's avatar
knopp committed
622

623
void init_openair0(void) {
knopp's avatar
knopp committed
624
625
626
627
628
629
630
631
632
633
634
635

  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;
636
	openair0_cfg[card].samples_per_frame = 230400;
knopp's avatar
knopp committed
637
638
	openair0_cfg[card].tx_bw = 10e6;
	openair0_cfg[card].rx_bw = 10e6;
639
      } else {
knopp's avatar
knopp committed
640
	openair0_cfg[card].sample_rate=30.72e6;
641
	openair0_cfg[card].samples_per_frame = 307200;
knopp's avatar
knopp committed
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
	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,
669
670
	   RC.eNB[0][0]->frame_parms.nb_antennas_tx ,
	   RC.eNB[0][0]->frame_parms.nb_antennas_rx );
knopp's avatar
knopp committed
671
672
673
    openair0_cfg[card].Mod_id = 0;

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

675
    openair0_cfg[card].clock_source = clock_source;
676

677

678
679
    openair0_cfg[card].tx_num_channels=min(2,RC.eNB[0][0]->frame_parms.nb_antennas_tx );
    openair0_cfg[card].rx_num_channels=min(2,RC.eNB[0][0]->frame_parms.nb_antennas_rx );
680

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

knopp's avatar
knopp committed
683
      if (i<openair0_cfg[card].tx_num_channels)
684
	openair0_cfg[card].tx_freq[i] = downlink_frequency[0][i] ;
knopp's avatar
knopp committed
685
686
      else
	openair0_cfg[card].tx_freq[i]=0.0;
687

knopp's avatar
knopp committed
688
      if (i<openair0_cfg[card].rx_num_channels)
689
	openair0_cfg[card].rx_freq[i] =downlink_frequency[0][i] + uplink_frequency_offset[0][i] ;
knopp's avatar
knopp committed
690
691
692
693
694
      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];
695
696
      openair0_cfg[card].rx_gain[i] = RC.eNB[0][0]->rx_total_gain_dB;

knopp's avatar
knopp committed
697

698
      openair0_cfg[card].configFilename = rf_config_file;
699
      printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n",
700
701
702
703
	     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]);
704
    }
705
  } /* for loop on cards */
knopp's avatar
   
knopp committed
706
}
707

708

709
void wait_RUs(void) {
710

711
  LOG_I(PHY,"Waiting for RUs to be configured ... RC.ru_mask:%02lx\n", RC.ru_mask);
712
713
714
715
716

  // 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);
717
    printf("RC.ru_mask:%02lx\n", RC.ru_mask);
718
  }
719
  pthread_mutex_unlock(&RC.ru_mutex);
720
721
722
723

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

724
void wait_eNBs(void) {
725
726
727
728
729
730

  int i,j;
  int waiting=1;


  while (waiting==1) {
Cedric Roux's avatar
Cedric Roux committed
731
732
    printf("Waiting for eNB L1 instances to all get configured ... sleeping 50ms (nb_L1_inst %d)\n",RC.nb_L1_inst);
    usleep(50*1000);
733
    waiting=0;
734
735
736
737
738
    for (i=0;i<RC.nb_L1_inst;i++) {

      printf("RC.nb_L1_CC[%d]:%d\n", i, RC.nb_L1_CC[i]);

      for (j=0;j<RC.nb_L1_CC[i];j++) {
739
740
741
	if (RC.eNB[i][j]->configured==0) {
	  waiting=1;
	  break;
742
743
744
        } 
      }
    }
745
746
747
  }
  printf("eNB L1 are configured\n");
}
748

749
#if defined(ENABLE_ITTI)
750
751
/*
 * helper function to terminate a certain ITTI task
752
 */
753
void terminate_task(task_id_t task_id, module_id_t mod_id)
754
{
755
756
757
758
759
760
  LOG_I(ENB_APP, "sending TERMINATE_MESSAGE to task %s (%d)\n", itti_get_task_name(task_id), task_id);
  MessageDef *msg;
  msg = itti_alloc_new_message (ENB_APP, TERMINATE_MESSAGE);
  itti_send_msg_to_task (task_id, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg);
}

761
extern void  free_transport(PHY_VARS_eNB *);
762
763
extern void  phy_free_RU(RU_t*);

764
int stop_L1L2(module_id_t enb_id)
765
766
{
  LOG_W(ENB_APP, "stopping lte-softmodem\n");
767
  oai_exit = 1;
768

769
770
771
772
773
774
775
776
777
778
779
780
  if (!RC.ru) {
    LOG_F(ENB_APP, "no RU configured\n");
    return -1;
  }

  /* stop trx devices, multiple carrier currently not supported by RU */
  if (RC.ru[enb_id]) {
    if (RC.ru[enb_id]->rfdevice.trx_stop_func) {
      RC.ru[enb_id]->rfdevice.trx_stop_func(&RC.ru[enb_id]->rfdevice);
      LOG_I(ENB_APP, "turned off RU rfdevice\n");
    } else {
      LOG_W(ENB_APP, "can not turn off rfdevice due to missing trx_stop_func callback, proceding anyway!\n");
781
    }
782
783
784
785
786
    if (RC.ru[enb_id]->ifdevice.trx_stop_func) {
      RC.ru[enb_id]->ifdevice.trx_stop_func(&RC.ru[enb_id]->ifdevice);
      LOG_I(ENB_APP, "turned off RU ifdevice\n");
    } else {
      LOG_W(ENB_APP, "can not turn off ifdevice due to missing trx_stop_func callback, proceding anyway!\n");
787
    }
788
789
790
  } else {
    LOG_W(ENB_APP, "no RU found for index %d\n", enb_id);
    return -1;
791
792
793
794
795
  }

  /* these tasks need to pick up new configuration */
  terminate_task(TASK_RRC_ENB, enb_id);
  terminate_task(TASK_L2L1, enb_id);
796
  LOG_I(ENB_APP, "calling kill_eNB_proc() for instance %d\n", enb_id);
797
  kill_eNB_proc(enb_id);
798
799
  LOG_I(ENB_APP, "calling kill_RU_proc() for instance %d\n", enb_id);
  kill_RU_proc(enb_id);
800
  oai_exit = 0;
801
802
803
804
  for (int cc_id = 0; cc_id < RC.nb_CC[enb_id]; cc_id++) {
    free_transport(RC.eNB[enb_id][cc_id]);
    phy_free_lte_eNB(RC.eNB[enb_id][cc_id]);
  }
805
  phy_free_RU(RC.ru[enb_id]);
806
  free_lte_top();
807
808
809
810
  return 0;
}

/*
811
 * Restart the lte-softmodem after it has been soft-stopped with stop_L1L2()
812
 */
813
int restart_L1L2(module_id_t enb_id)
814
{
815
816
817
  RU_t *ru = RC.ru[enb_id];
  int cc_id;
  MessageDef *msg_p = NULL;
818
819
820
821
822
823

  LOG_W(ENB_APP, "restarting lte-softmodem\n");

  /* block threads */
  sync_var = -1;

824
825
  for (cc_id = 0; cc_id < RC.nb_L1_CC[enb_id]; cc_id++) {
    RC.eNB[enb_id][cc_id]->configured = 0;
826
827
  }

828
829
830
831
832
  RC.ru_mask |= (1 << ru->idx);
  /* copy the changed frame parameters to the RU */
  /* TODO this should be done for all RUs associated to this eNB */
  memcpy(&ru->frame_parms, &RC.eNB[enb_id][0]->frame_parms, sizeof(LTE_DL_FRAME_PARMS));
  set_function_spec_param(RC.ru[enb_id]);
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847

  LOG_I(ENB_APP, "attempting to create ITTI tasks\n");
  if (itti_create_task (TASK_RRC_ENB, rrc_enb_task, NULL) < 0) {
    LOG_E(RRC, "Create task for RRC eNB failed\n");
    return -1;
  } else {
    LOG_I(RRC, "Re-created task for RRC eNB successfully\n");
  }
  if (itti_create_task (TASK_L2L1, l2l1_task, NULL) < 0) {
    LOG_E(PDCP, "Create task for L2L1 failed\n");
    return -1;
  } else {
    LOG_I(PDCP, "Re-created task for L2L1 successfully\n");
  }

848
849
850
851
852
  /* pass a reconfiguration request which will configure everything down to
   * RC.eNB[i][j]->frame_parms, too */
  msg_p = itti_alloc_new_message(TASK_ENB_APP, RRC_CONFIGURATION_REQ);
  RRC_CONFIGURATION_REQ(msg_p) = RC.rrc[enb_id]->configuration;
  itti_send_msg_to_task(TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
853
854
  /* TODO XForms might need to be restarted, but it is currently (09/02/18)
   * broken, so we cannot test it */
855

856
857
858
859
860
861
  wait_eNBs();
  init_RU_proc(ru);
  ru->rf_map.card = 0;
  ru->rf_map.chain = 0; /* CC_id + chain_offset;*/
  wait_RUs();
  init_eNB_afterRU();
862
863
864
865
866
867
868
869

  printf("Sending sync to all threads\n");
  pthread_mutex_lock(&sync_mutex);
  sync_var=0;
  pthread_cond_broadcast(&sync_cond);
  pthread_mutex_unlock(&sync_mutex);

  return 0;
870
}
871
#endif
872

873
static  void wait_nfapi_init(char *thread_name) {
874
875
876
877
878
879
880
881
882
883
884
885

  printf( "waiting for NFAPI PNF connection and population of global structure (%s)\n",thread_name);
  pthread_mutex_lock( &nfapi_sync_mutex );
  
  while (nfapi_sync_var<0)
    pthread_cond_wait( &nfapi_sync_cond, &nfapi_sync_mutex );
  
  pthread_mutex_unlock(&nfapi_sync_mutex);
  
  printf( "NFAPI: got sync (%s)\n", thread_name);
}

886
887
int main( int argc, char **argv )
{
888
  int i;
889
#if defined (XFORMS)
knopp's avatar
   
knopp committed
890
  void *status;
891
#endif
892

knopp's avatar
   
knopp committed
893
  int CC_id;
894
  int ru_id;
knopp's avatar
   
knopp committed
895
#if defined (XFORMS)
896
897
  int ret;
#endif
898

899
  start_background_system();
900
901
902
903
  if ( load_configmodule(argc,argv) == NULL) {
    exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
  } 
      
904
905
906
907
908
#ifdef DEBUG_CONSOLE
  setvbuf(stdout, NULL, _IONBF, 0);
  setvbuf(stderr, NULL, _IONBF, 0);
#endif

909
  mode = normal_txrx;
910
  memset(&openair0_cfg[0],0,sizeof(openair0_config_t)*MAX_CARDS);
911

912
  memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
913

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

916
  logInit();
knopp's avatar
knopp committed
917

918
  printf("Reading in command-line options\n");
919

920
  get_options (); 
921
  if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) {
oai's avatar
oai committed
922
923
      fprintf(stderr,"Getting configuration failed\n");
      exit(-1);
924
  }
knopp's avatar
knopp committed
925
926


927
#if T_TRACER
Cedric Roux's avatar
Cedric Roux committed
928
  T_init(T_port, 1-T_nowait, T_dont_fork);
929
930
#endif