lte-softmodem.c 103 KB
Newer Older
1
/*******************************************************************************
2 3
    OpenAirInterface 
    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 17 18 19
    You should have received a copy of the GNU General Public License
    along with OpenAirInterface.The full GNU General Public License is 
    included in this distribution in the file called "COPYING". If not, 
    see <http://www.gnu.org/licenses/>.
20

21 22 23 24 25
   Contact Information
   OpenAirInterface Admin: openair_admin@eurecom.fr
   OpenAirInterface Tech : openair_tech@eurecom.fr
   OpenAirInterface Dev  : openair4g-devel@eurecom.fr
  
ghaddab's avatar
ghaddab committed
26
   Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
27

28
 *******************************************************************************/
29 30

/*! \file lte-softmodem.c
knopp's avatar
 
knopp committed
31
 * \brief main program to control HW and scheduling
32
 * \author R. Knopp, F. Kaltenberger, Navid Nikaein
knopp's avatar
 
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
knopp's avatar
 
knopp committed
37 38 39
 * \note
 * \warning
 */
knopp's avatar
 
knopp committed
40
#define _GNU_SOURCE
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
#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 <sys/stat.h>
#include <fcntl.h>
#include <sched.h>
#include <signal.h>
#include <execinfo.h>
#include <getopt.h>

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

knopp's avatar
 
knopp committed
58
#ifdef USRP
knopp's avatar
 
knopp committed
59
static int hw_subframe;
knopp's avatar
 
knopp committed
60
#endif
knopp's avatar
 
knopp committed
61

62
#include "assertions.h"
63 64 65 66 67 68

#ifdef EMOS
#include <gps.h>
#endif

#include "PHY/types.h"
69

70
#include "PHY/defs.h"
71 72 73
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all

knopp's avatar
 
knopp committed
74
#ifndef USRP
75
#include "openair0_lib.h"
knopp's avatar
 
knopp committed
76 77 78 79
#else
#include "../../ARCH/COMMON/common_lib.h"
#endif

80
#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
81 82 83

#include "PHY/vars.h"
#include "MAC_INTERFACE/vars.h"
84
//#include "SCHED/defs.h"
85 86 87 88 89 90 91 92 93 94
#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
95
#include "otg_tx.h"
96 97
#include "LAYER2/MAC/defs.h"
#include "LAYER2/MAC/vars.h"
98
#include "LAYER2/MAC/proto.h"
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
#ifndef CELLULAR
#include "RRC/LITE/vars.h"
#endif
#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"
#include "UTIL/OTG/otg.h"
#include "UTIL/OTG/otg_vars.h"
#include "UTIL/MATH/oml.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
114
#include "enb_config.h"
115

116 117
#if defined(ENABLE_ITTI)
# include "intertask_interface_init.h"
118
# include "create_tasks.h"
119 120 121
# if defined(ENABLE_USE_MME)
#   include "s1ap_eNB.h"
# endif
122 123
#endif

124 125 126
#ifdef XFORMS
#include "PHY/TOOLS/lte_phy_scope.h"
#include "stats.h"
127 128 129 130 131
#endif

#define FRAME_PERIOD    100000000ULL
#define DAQ_PERIOD      66667ULL

knopp's avatar
 
knopp committed
132 133
#define DEBUG_THREADS 1

134 135 136 137 138 139 140
struct timing_info_t {
  //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;
} timing_info;

gauthier's avatar
gauthier committed
141 142
extern int16_t* sync_corr_ue0;
extern int16_t prach_ifft[4][1024*2];
143 144 145

int init_dlsch_threads(void);
void cleanup_dlsch_threads(void);
gauthier's avatar
gauthier committed
146
int32_t init_rx_pdsch_thread(void);
147
void cleanup_rx_pdsch_thread(void);
knopp's avatar
 
knopp committed
148

149
openair0_config_t openair0_cfg[MAX_CARDS];
knopp's avatar
 
knopp committed
150

knopp's avatar
 
knopp committed
151 152
int32_t *rxdata;
int32_t *txdata;
153 154
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]);
155 156

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

#ifdef RTAI
167
static SEM                     *mutex;
168 169
//static CND *cond;

knopp's avatar
 
knopp committed
170 171
static int                      main_eNB_thread;
static int                      main_ue_thread;
knopp's avatar
 
knopp committed
172 173 174
#ifdef USRP
static SEM *sync_sem; // to sync rx & tx streaming
#endif
175 176
//static int sync_thread;
#else
knopp's avatar
 
knopp committed
177 178
pthread_t                       main_eNB_thread;
pthread_t                       main_ue_thread;
179 180
pthread_attr_t                  attr_dlsch_threads;
struct sched_param              sched_param_dlsch;
knopp's avatar
 
knopp committed
181

knopp's avatar
 
knopp committed
182 183 184 185
#ifdef USRP
pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex;
#endif
186 187
#endif

knopp's avatar
 
knopp committed
188 189 190
pthread_attr_t                  attr_UE_init_synch;
pthread_attr_t                  attr_UE_thread_tx;
pthread_attr_t                  attr_UE_thread_rx;
knopp's avatar
 
knopp committed
191 192
pthread_attr_t                  attr_eNB_proc_tx[MAX_NUM_CCs][10];
pthread_attr_t                  attr_eNB_proc_rx[MAX_NUM_CCs][10];
knopp's avatar
 
knopp committed
193 194 195
struct sched_param              sched_param_UE_init_synch;
struct sched_param              sched_param_UE_thread_tx;
struct sched_param              sched_param_UE_thread_rx;
knopp's avatar
 
knopp committed
196 197
struct sched_param              sched_param_eNB_proc_tx[MAX_NUM_CCs][10];
struct sched_param              sched_param_eNB_proc_rx[MAX_NUM_CCs][10];
knopp's avatar
 
knopp committed
198

199
#ifdef XFORMS
knopp's avatar
 
knopp committed
200
static pthread_t                forms_thread; //xforms
201 202 203 204
#endif
#ifdef EMOS
static pthread_t                thread3; //emos
#endif
205

206 207 208 209
#ifdef SPECTRA
static pthread_t sensing_thread;
#endif

knopp's avatar
 
knopp committed
210 211 212
openair0_device openair0;
openair0_timestamp timestamp;

213
/*
knopp's avatar
 
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;
knopp's avatar
 
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};

knopp's avatar
 
knopp committed
234

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

238
//uint32_t                        carrier_freq[MAX_NUM_CCs][4] =           {{1907600000,1907600000,1907600000,1907600000}}; /* For UE! */
239
static uint32_t                 downlink_frequency[MAX_NUM_CCs][4] =     {{1907600000,1907600000,1907600000,1907600000}};
240 241 242
static int32_t                  uplink_frequency_offset[MAX_NUM_CCs][4]= {{0,0,0,0}};

openair0_rf_map rf_map[MAX_NUM_CCs];
243

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

gauthier's avatar
gauthier committed
249
#ifndef USRP
250 251
double tx_gain[MAX_NUM_CCs][4] = {{20,20,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{20,20,0,0}};
252
// these are for EXMIMO2 target only
253
/*
254 255 256
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};
257 258 259 260 261 262 263 264
*/
// these are for EXMIMO2 card 39
static unsigned int             rxg_max[4] =    {128,128,128,126};
static unsigned int             rxg_med[4] =    {122,123,123,120};
static unsigned int             rxg_byp[4] =    {116,117,116,116};
static unsigned int             nf_max[4] =    {7,9,16,12};
static unsigned int             nf_med[4] =    {12,13,22,17};
static unsigned int             nf_byp[4] =    {15,20,29,23};
265
static rx_gain_t                rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain}};
gauthier's avatar
gauthier committed
266
#else
267 268
double tx_gain[MAX_NUM_CCs][4] = {{120,0,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{50,0,0,0}};
gauthier's avatar
gauthier committed
269
#endif
knopp's avatar
 
knopp committed
270

knopp's avatar
 
knopp committed
271 272
double sample_rate=30.72e6;
double bw = 14e6;
273

274
static int                      tx_max_power[MAX_NUM_CCs] =  {{0}};
275

276
#ifdef USRP
knopp's avatar
 
knopp committed
277 278 279
char ref[128] = "internal";
char channels[128] = "0";

knopp's avatar
 
knopp committed
280 281 282
unsigned int samples_per_frame = 307200;
unsigned int samples_per_packets = 2048; // samples got every recv or send
unsigned int tx_forward_nsamps;
knopp's avatar
 
knopp committed
283 284 285 286 287 288 289 290 291

int sf_bounds_5[10] = {8, 15, 23, 30, 38, 45, 53, 60, 68, 75};
int sf_bounds_10[10] = {8, 15, 23, 30, 38, 45, 53, 60, 68, 75};
int sf_bounds_20[10] = {15, 30, 45, 60, 75, 90, 105, 120, 135, 150};
int *sf_bounds;
int max_cnt;
int tx_delay;

#endif
292
/*
knopp's avatar
 
knopp committed
293 294 295
  uint32_t rf_mode_max[4]     = {55759,55759,55759,55759};
  uint32_t rf_mode_med[4]     = {39375,39375,39375,39375};
  uint32_t rf_mode_byp[4]     = {22991,22991,22991,22991};
296
*/
knopp's avatar
 
knopp committed
297 298
//static uint32_t                      rf_mode[4] =        {MY_RF_MODE,0,0,0};
//static uint32_t                      rf_local[4] =       {8255000,8255000,8255000,8255000}; // UE zepto
knopp's avatar
 
knopp committed
299 300
//{8254617, 8254617, 8254617, 8254617}; //eNB khalifa
//{8255067,8254810,8257340,8257340}; // eNB PETRONAS
301

knopp's avatar
 
knopp committed
302 303 304 305 306
//static uint32_t                      rf_vcocal[4] =      {910,910,910,910};
//static uint32_t                      rf_vcocal_850[4] =  {2015, 2015, 2015, 2015};
//static uint32_t                      rf_rxdc[4] =        {32896,32896,32896,32896};
//static uint32_t                      rxgain[4] =         {20,20,20,20};
//static uint32_t                      txgain[4] =         {20,20,20,20};
307 308 309

static runmode_t                mode;
static int                      rx_input_level_dBm;
310
static int                      online_log_messages=0;
311
#ifdef XFORMS
312
extern int                      otg_enabled;
313
static char                     do_forms=0;
314
#else
315
int                             otg_enabled;
316
#endif
knopp's avatar
 
knopp committed
317
//int                             number_of_cards =   1;
knopp's avatar
 
knopp committed
318
#ifndef USRP
319 320
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
knopp's avatar
 
knopp committed
321
#endif
322

knopp's avatar
 
knopp committed
323
static LTE_DL_FRAME_PARMS      *frame_parms[MAX_NUM_CCs];
324

knopp's avatar
 
knopp committed
325
int multi_thread=1;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
326
uint32_t target_dl_mcs = 28; //maximum allowed mcs
327 328
uint32_t target_ul_mcs = 8;

knopp's avatar
 
knopp committed
329

330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
int16_t           glog_level=LOG_DEBUG;
int16_t           glog_verbosity=LOG_MED;
int16_t           hw_log_level=LOG_DEBUG;
int16_t           hw_log_verbosity=LOG_MED;
int16_t           phy_log_level=LOG_DEBUG;
int16_t           phy_log_verbosity=LOG_MED;
int16_t           mac_log_level=LOG_DEBUG;
int16_t           mac_log_verbosity=LOG_MED;
int16_t           rlc_log_level=LOG_DEBUG;
int16_t           rlc_log_verbosity=LOG_MED;
int16_t           pdcp_log_level=LOG_DEBUG;
int16_t           pdcp_log_verbosity=LOG_MED;
int16_t           rrc_log_level=LOG_DEBUG;
int16_t           rrc_log_verbosity=LOG_MED;

345
unsigned int build_rflocal(int txi, int txq, int rxi, int rxq)
346
{
knopp's avatar
 
knopp committed
347
  return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
348 349 350
}
unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe)
{
knopp's avatar
 
knopp committed
351
  return (dcoff_i_rxfe + (dcoff_q_rxfe<<8));
352 353
}

354
#if !defined(ENABLE_ITTI)
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369
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);
    
    // print out all the frames to stderr
    fprintf(stderr, "Error: signal %d:\n", sig);
    backtrace_symbols_fd(array, size, 2);
    exit(-1);
  }
  else {
370
    oai_exit = 1;
371 372
  }
}
373
#endif
374 375 376

void exit_fun(const char* s)
{
377
  if (s != NULL) {
gauthier's avatar
gauthier committed
378
    printf("%s %s() Exiting: %s\n",__FILE__, __FUNCTION__, s);
379 380 381 382 383
  }

  oai_exit = 1;

#if defined(ENABLE_ITTI)
384
  itti_terminate_tasks (TASK_UNKNOWN);
385
#endif
386 387 388 389 390 391

  //rt_sleep_ns(FRAME_PERIOD);

  //exit (-1);
}

knopp's avatar
 
knopp committed
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 417 418 419 420 421
static int latency_target_fd = -1;
static int32_t latency_target_value = 0;
/* Latency trick - taken from cyclictest.c 
* if the file /dev/cpu_dma_latency exists,
* open it and write a zero into it. This will tell
* the power management system not to transition to
* a high cstate (in fact, the system acts like idle=poll)
* When the fd to /dev/cpu_dma_latency is closed, the behavior
* goes back to the system default.
*
* Documentation/power/pm_qos_interface.txt
*/
static void set_latency_target(void)
{
  struct stat s;
  int ret;
  if (stat("/dev/cpu_dma_latency", &s) == 0) {
    latency_target_fd = open("/dev/cpu_dma_latency", O_RDWR);
    if (latency_target_fd == -1)
      return;
    ret = write(latency_target_fd, &latency_target_value, 4);
    if (ret == 0) {
      printf("# error setting cpu_dma_latency to %d!: %s\n", latency_target_value, strerror(errno));
      close(latency_target_fd);
      return;
    }
    printf("# /dev/cpu_dma_latency set to %dus\n", latency_target_value);
  }
}

422
#ifdef XFORMS
423
static void *scope_thread(void *arg) {
knopp's avatar
 
knopp committed
424
  char stats_buffer[16384];
425
# ifdef ENABLE_XFORMS_WRITE_STATS
knopp's avatar
 
knopp committed
426 427
  FILE *UE_stats, *eNB_stats;
  int len = 0;
428
# endif
knopp's avatar
 
knopp committed
429
  struct sched_param sched_param;
430

knopp's avatar
 
knopp committed
431 432
  sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1; 
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
433

knopp's avatar
 
knopp committed
434
  printf("Scope thread has priority %d\n",sched_param.sched_priority);
435
    
knopp's avatar
 
knopp committed
436 437 438 439 440 441
  /*
    if (UE_flag==1) 
    UE_stats  = fopen("UE_stats.txt", "w");
    else 
    eNB_stats = fopen("eNB_stats.txt", "w");
  */
442
    
knopp's avatar
 
knopp committed
443 444
  while (!oai_exit) {
    if (UE_flag==1) {
445
# ifdef ENABLE_XFORMS_WRITE_STATS
knopp's avatar
 
knopp committed
446
      len =
447
# endif
448
	dump_ue_stats (PHY_vars_UE_g[0][0], stats_buffer, 0, mode,rx_input_level_dBm);
knopp's avatar
 
knopp committed
449
      fl_set_object_label(form_stats->stats_text, stats_buffer);
450
# ifdef ENABLE_XFORMS_WRITE_STATS
knopp's avatar
 
knopp committed
451 452
      rewind (UE_stats);
      fwrite (stats_buffer, 1, len, UE_stats);
453
# endif
knopp's avatar
 
knopp committed
454
      phy_scope_UE(form_ue[UE_id], 
455
		   PHY_vars_UE_g[UE_id][0],
knopp's avatar
 
knopp committed
456 457
		   eNB_id,
		   UE_id,7);
458
            
knopp's avatar
 
knopp committed
459
    } else {
460
# ifdef ENABLE_XFORMS_WRITE_STATS
knopp's avatar
 
knopp committed
461
      len =
462
# endif
knopp's avatar
 
knopp committed
463
	dump_eNB_stats (PHY_vars_eNB_g[0][0], stats_buffer, 0);
knopp's avatar
 
knopp committed
464
      fl_set_object_label(form_stats->stats_text, stats_buffer);
465
# ifdef ENABLE_XFORMS_WRITE_STATS
knopp's avatar
 
knopp committed
466 467
      rewind (eNB_stats);
      fwrite (stats_buffer, 1, len, eNB_stats);
468
# endif
469 470
      dump_eNB_l2_stats (stats_buffer, 0);
      fl_set_object_label(form_stats_l2->stats_text, stats_buffer);
knopp's avatar
 
knopp committed
471 472
      for(UE_id=0;UE_id<scope_enb_num_ue;UE_id++) {
	phy_scope_eNB(form_enb[UE_id], 
knopp's avatar
 
knopp committed
473
		      PHY_vars_eNB_g[eNB_id][0],
knopp's avatar
 
knopp committed
474 475
		      UE_id);
      }
476 477
              
    }
knopp's avatar
 
knopp committed
478
    //printf("doing forms\n");
Florian Kaltenberger's avatar
Florian Kaltenberger committed
479 480
    //usleep(100000); // 100 ms
    sleep(1);
knopp's avatar
 
knopp committed
481
  }
482
    
483
# ifdef ENABLE_XFORMS_WRITE_STATS
knopp's avatar
 
knopp committed
484 485
  fclose (UE_stats);
  fclose (eNB_stats);
486
# endif
487
    
knopp's avatar
 
knopp committed
488
  pthread_exit((void*)arg);
489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
}
#endif

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

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;
  
  int channel_buffer_size;
  
  time_t timer;
  struct tm *now;

  struct gps_data_t *gps_data = NULL;
  struct gps_fix_t dummy_gps_data;
514 515 516 517 518 519 520

  struct sched_param sched_param;
  
  sched_param.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; 
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
  
  printf("EMOS thread has priority %d\n",sched_param.sched_priority);
521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542
 
  timer = time(NULL);
  now = localtime(&timer);

  memset(&dummy_gps_data,1,sizeof(struct gps_fix_t));
  
  gps_data = gps_open("127.0.0.1","2947");
  if (gps_data == NULL) 
    {
      printf("[EMOS] Could not open GPS\n");
      //exit(-1);
    }
#if GPSD_API_MAJOR_VERSION>=4
  else if (gps_stream(gps_data, WATCH_ENABLE,NULL) != 0)
#else
  else if (gps_query(gps_data, "w+x") != 0)
#endif
    {
      //sprintf(tmptxt,"Error sending command to GPS, gps_data = %x", gps_data);
      printf("[EMOS] Error sending command to GPS\n");
      //exit(-1);
    }
543 544
  else 
    printf("[EMOS] Opened GPS, gps_data=%p\n");
545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589
  
  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;

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

  if ((fifo = open(CHANSOUNDER_FIFO_DEV, O_RDONLY)) < 0)
    {
      fprintf(stderr, "[EMOS] Error opening the fifo\n");
      exit(EXIT_FAILURE);
    }


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

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


  printf("[EMOS] starting dump, channel_buffer_size=%d ...\n",channel_buffer_size);
  while (!oai_exit)
    {
      bytes = rtf_read_timed(fifo, fifo2file_ptr, channel_buffer_size,100);
      if (bytes==0)
	continue;

      /*
knopp's avatar
 
knopp committed
590
	if (UE_flag==0)
591
	printf("eNB: count %d, frame %d, read: %d bytes from the fifo\n",counter, ((fifo_dump_emos_eNB*)fifo2file_ptr)->frame_tx,bytes);
knopp's avatar
 
knopp committed
592
	else
593 594 595 596 597 598 599 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 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653
	printf("UE: count %d, frame %d, read: %d bytes from the fifo\n",counter, ((fifo_dump_emos_UE*)fifo2file_ptr)->frame_rx,bytes);
      */

      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);
            }
	  if (gps_data)
	    {
	      if (gps_poll(gps_data) != 0) {
		printf("[EMOS] problem polling data from gps\n");
	      }
	      else {
		printf("[EMOS] lat %g, lon %g\n",gps_data->fix.latitude,gps_data->fix.longitude);
	      }
	      if (fwrite(&(gps_data->fix), 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);
		}
	    }
	  else
	    {
	      printf("[EMOS] WARNING: No GPS data available, storing dummy packet\n");
	      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);
		}
	    } 
        }
    }
  
  free(fifo2file_buffer);
  fclose(dumpfile_id);
  close(fifo);
  
  pthread_exit((void*) arg);

}
#endif

654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686
#ifdef SPECTRA
void *sensing (void *arg)
{
  struct sched_param sched_param;
  
  sched_param.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; 
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
  
  printf("[SPECTRA] sensing thread started with priority %d\n",sched_param.sched_priority);
 
  while (oai_exit==0) {

    
    openair0_cfg[1].rx_freq[0]+= 5e6;
    if (openair0_cfg[1].rx_freq[0] >= 750000000)
      openair0_cfg[1].rx_freq[0] = 727500000;
    

    LOG_I(HW,"[SPECTRA] changing frequency to %u \n",(uint32_t)openair0_cfg[1].rx_freq[0]);

    openair0_reconfig(&openair0_cfg[0]);

    usleep(250000);
    //sleep(1);
    
  }

  pthread_exit((void*) arg);

}
#endif


687
#if defined(ENABLE_ITTI)
688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705
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[] = {".    ", "..   ", "...  ", ".... ", ".....",
                                " ....", "  ...", "   ..", "    .", "     "};
    int i = 0;

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

knopp's avatar
 
knopp committed
706
#if defined(ENABLE_ITTI)
707
void *l2l1_task(void *arg)
708
{
knopp's avatar
 
knopp committed
709 710 711 712 713
  MessageDef *message_p = NULL;
  int         result;

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
714

knopp's avatar
 
knopp committed
715 716
  if (UE_flag == 0) {
    /* Wait for the initialize message */
717
    do {
knopp's avatar
 
knopp committed
718 719 720 721
      if (message_p != NULL) {
	result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
	AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
      }
722 723 724
      itti_receive_msg (TASK_L2L1, &message_p);

      switch (ITTI_MSG_ID(message_p)) {
knopp's avatar
 
knopp committed
725 726 727 728 729 730 731 732 733 734 735 736 737 738
      case INITIALIZE_MESSAGE:
	/* Start eNB thread */
	LOG_D(EMU, "L2L1 TASK received %s\n", ITTI_MSG_NAME(message_p));
	start_eNB = 1;
	break;

      case TERMINATE_MESSAGE:
	oai_exit=1;
	itti_exit_task ();
	break;

      default:
	LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
	break;
739
      }
knopp's avatar
 
knopp committed
740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761
    } while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE);
    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;
762

knopp's avatar
 
knopp committed
763 764 765 766 767 768 769 770 771 772 773 774
    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);
  } while(1);
775

knopp's avatar
 
knopp committed
776
  return NULL;
777 778 779
}
#endif

knopp's avatar
 
knopp committed
780

knopp's avatar
 
knopp committed
781
void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) {
knopp's avatar
 
knopp committed
782 783 784 785

  unsigned int aa,slot_offset, slot_offset_F;
  int dummy_tx_b[7680*4] __attribute__((aligned(16)));
  int i, tx_offset;
knopp's avatar
 
knopp committed
786
  int slot_sizeF = (phy_vars_eNB->lte_frame_parms.ofdm_symbol_size)*
knopp's avatar
 
knopp committed
787
    ((phy_vars_eNB->lte_frame_parms.Ncp==1) ? 6 : 7);
knopp's avatar
 
knopp committed
788 789 790

  slot_offset_F = (subframe<<1)*slot_sizeF;
    
knopp's avatar
 
knopp committed
791 792
  slot_offset = subframe*phy_vars_eNB->lte_frame_parms.samples_per_tti;

knopp's avatar
 
knopp committed
793 794
  if ((subframe_select(&phy_vars_eNB->lte_frame_parms,subframe)==SF_DL)||
      ((subframe_select(&phy_vars_eNB->lte_frame_parms,subframe)==SF_S))) {
knopp's avatar
 
knopp committed
795
    //	  LOG_D(HW,"Frame %d: Generating slot %d\n",frame,next_slot);
knopp's avatar
 
knopp committed
796

knopp's avatar
 
knopp committed
797
    
knopp's avatar
 
knopp committed
798 799 800 801 802 803 804 805 806 807
    for (aa=0; aa<phy_vars_eNB->lte_frame_parms.nb_antennas_tx; aa++) {
      if (phy_vars_eNB->lte_frame_parms.Ncp == EXTENDED){ 
	PHY_ofdm_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F],
		     dummy_tx_b,
		     phy_vars_eNB->lte_frame_parms.log2_symbol_size,
		     6,
		     phy_vars_eNB->lte_frame_parms.nb_prefix_samples,
		     phy_vars_eNB->lte_frame_parms.twiddle_ifft,
		     phy_vars_eNB->lte_frame_parms.rev,
		     CYCLIC_PREFIX);
knopp's avatar
 
knopp committed
808 809 810 811 812 813 814 815
	PHY_ofdm_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F+slot_sizeF],
		     dummy_tx_b+(phy_vars_eNB->lte_frame_parms.samples_per_tti>>1),
		     phy_vars_eNB->lte_frame_parms.log2_symbol_size,
		     6,
		     phy_vars_eNB->lte_frame_parms.nb_prefix_samples,
		     phy_vars_eNB->lte_frame_parms.twiddle_ifft,
		     phy_vars_eNB->lte_frame_parms.rev,
		     CYCLIC_PREFIX);
knopp's avatar
 
knopp committed
816 817 818 819 820 821
      }
      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));
knopp's avatar
 
knopp committed
822 823 824 825
	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));
knopp's avatar
 
knopp committed
826
      }
knopp's avatar
 
knopp committed
827 828

      for (i=0; i<phy_vars_eNB->lte_frame_parms.samples_per_tti; i++) {
knopp's avatar
 
knopp committed
829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845
	tx_offset = (int)slot_offset+time_offset[aa]+i;
	if (tx_offset<0)
	  tx_offset += LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti;
	if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti))
	  tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti;
	((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[0]=
	  ((short*)dummy_tx_b)[2*i]<<4;
	((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[1]=
	  ((short*)dummy_tx_b)[2*i+1]<<4;
      }
    }
  }
}


int eNB_thread_tx_status[10];
static void * eNB_thread_tx(void *param) {
knopp's avatar
 
knopp committed
846 847 848

  //unsigned long cpuid;
  eNB_proc_t *proc = (eNB_proc_t*)param;
knopp's avatar
 
knopp committed
849
  //  RTIME time_in,time_out;
knopp's avatar
 
knopp committed
850 851
#ifdef RTAI
  RT_TASK *task;
852
  char task_name[8];
knopp's avatar
 
knopp committed
853
#endif
knopp's avatar
 
knopp committed
854 855

 
knopp's avatar
 
knopp committed
856

knopp's avatar
 
knopp committed
857 858 859 860 861
#if defined(ENABLE_ITTI)
  /* Wait for eNB application initialization to be complete (eNB registration to MME) */
  wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB);
#endif

knopp's avatar
 
knopp committed
862
#ifdef RTAI
863
  sprintf(task_name,"TXC%dS%d",proc->CC_id,proc->subframe);
knopp's avatar
 
knopp committed
864 865 866
  task = rt_task_init_schmod(nam2num(task_name), 0, 0, 0, SCHED_FIFO, 0xF);

  if (task==NULL) {
knopp's avatar
 
knopp committed
867
    LOG_E(PHY,"[SCHED][eNB] Problem starting eNB_proc_TX thread_index %d (%s)!!!!\n",proc->subframe,task_name);
knopp's avatar
 
knopp committed
868 869 870
    return 0;
  }
  else {
871 872
    LOG_I(PHY,"[SCHED][eNB] eNB TX thread CC %d SF %d started with id %p\n",
	  proc->CC_id,
knopp's avatar
 
knopp committed
873
	  proc->subframe,
874
	  task);
knopp's avatar
 
knopp committed
875
  }
knopp's avatar
 
knopp committed
876
#else
knopp's avatar
 
knopp committed
877 878 879
  //  LOG_I(PHY,
	printf("[SCHED][eNB] eNB TX thread %d started on CPU %d\n",
	       proc->subframe,sched_getcpu());
knopp's avatar
 
knopp committed
880 881 882 883 884 885 886 887 888 889 890 891
#endif

  mlockall(MCL_CURRENT | MCL_FUTURE);

  //rt_set_runnable_on_cpuid(task,1);
  //cpuid = rtai_cpuid();

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

  while (!oai_exit){
knopp's avatar
 
knopp committed
892
    
knopp's avatar
 
knopp committed
893
    vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe),0);
knopp's avatar
 
knopp committed
894 895
    
    
knopp's avatar
 
knopp committed
896
    //    LOG_I(PHY,"Locking mutex for eNB proc %d (IC %d,mutex %p)\n",proc->subframe,proc->instance_cnt,&proc->mutex);
knopp's avatar
 
knopp committed
897 898
    //printf("Locking mutex for eNB proc %d (subframe_tx %d))\n",proc->subframe,subframe_tx);

knopp's avatar
 
knopp committed
899 900
    if (pthread_mutex_lock(&proc->mutex_tx) != 0) {
      LOG_E(PHY,"[SCHED][eNB] error locking mutex for eNB TX proc %d\n",proc->subframe);
knopp's avatar
 
knopp committed
901
      oai_exit=1;
knopp's avatar
 
knopp committed
902 903
    }
    else {
knopp's avatar
 
knopp committed
904
      
knopp's avatar
 
knopp committed
905 906
      while (proc->instance_cnt_tx < 0) {
	//	LOG_I(PHY,"Waiting and unlocking mutex for eNB proc %d (IC %d,lock %d)\n",proc->subframe,proc->instance_cnt,pthread_mutex_trylock(&proc->mutex));
knopp's avatar
 
knopp committed
907
	//printf("Waiting and unlocking mutex for eNB proc %d (subframe_tx %d)\n",proc->subframe,subframe_tx);
knopp's avatar
 
knopp committed
908
	
knopp's avatar
 
knopp committed
909
	pthread_cond_wait(&proc->cond_tx,&proc->mutex_tx);
knopp's avatar
 
knopp committed
910
      }
knopp's avatar
 
knopp committed
911 912 913
      //      LOG_I(PHY,"Waking up and unlocking mutex for eNB proc %d\n",proc->subframe);
      if (pthread_mutex_unlock(&proc->mutex_tx) != 0) {	
	LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for eNB TX proc %d\n",proc->subframe);
knopp's avatar
 
knopp committed
914
	oai_exit=1;
knopp's avatar
 
knopp committed
915 916
      }
    }
knopp's avatar
 
knopp committed
917 918 919
    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_ENB, proc->frame_tx);
    vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_ENB, proc->subframe*2);
knopp's avatar
 
knopp committed
920
    
knopp's avatar
 
knopp committed
921
    if (oai_exit) break;
knopp's avatar
 
knopp committed
922

knopp's avatar
 
knopp committed
923 924 925 926 927 928 929
    
    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))||
	 (PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == FDD))) {
      
      phy_procedures_eNB_TX(proc->subframe,PHY_vars_eNB_g[0][proc->CC_id],0,no_relay,NULL);
      
knopp's avatar
 
knopp committed
930
    }
knopp's avatar
 
knopp committed
931 932
    if ((subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_tx)==SF_S)) {
      phy_procedures_eNB_TX(proc->subframe,PHY_vars_eNB_g[0][proc->CC_id],0,no_relay,NULL);
knopp's avatar
 
knopp committed
933
    }
knopp's avatar
 
knopp committed
934
    
knopp's avatar
 
knopp committed
935
    
knopp's avatar
 
knopp committed
936
    do_OFDM_mod_rt(proc->subframe_tx,PHY_vars_eNB_g[0][proc->CC_id]);  
knopp's avatar
 
knopp committed
937
    
knopp's avatar
 
knopp committed
938 939
    if (pthread_mutex_lock(&proc->mutex_tx) != 0) {
      printf("[openair][SCHED][eNB] error locking mutex for eNB TX proc %d\n",proc->subframe);
knopp's avatar
 
knopp committed
940
    }
knopp's avatar
 
knopp committed
941 942
    else {
      proc->instance_cnt_tx--;
knopp's avatar
 
knopp committed
943
      
knopp's avatar
 
knopp committed
944 945 946 947
      if (pthread_mutex_unlock(&proc->mutex_tx) != 0) {	
	printf("[openair][SCHED][eNB] error unlocking mutex for eNB TX proc %d\n",proc->subframe);
      }
    }
knopp's avatar
 
knopp committed
948
    
knopp's avatar
 
knopp committed
949 950 951
    proc->frame_tx++;
    if (proc->frame_tx==1024)
      proc->frame_tx=0;
knopp's avatar
 
knopp committed
952
  }    
knopp's avatar
 
knopp committed
953 954 955 956
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe),0);        
#ifdef HARD_RT
  rt_make_soft_real_time();
#endif
knopp's avatar
 
knopp committed
957
  
knopp's avatar
 
knopp committed
958 959 960 961 962 963 964 965 966 967
#ifdef DEBUG_THREADS
  printf("Exiting eNB thread TX %d\n",proc->subframe);
#endif
  // clean task
#ifdef RTAI
  rt_task_delete(task);
#else
  eNB_thread_tx_status[proc->subframe]=0;
  pthread_exit(&eNB_thread_tx_status[proc->subframe]);
#endif
knopp's avatar
 
knopp committed
968
  
knopp's avatar
 
knopp committed
969 970 971 972 973 974 975 976 977 978 979 980 981
#ifdef DEBUG_THREADS
  printf("Exiting eNB TX thread %d\n",proc->subframe);
#endif
}

int eNB_thread_rx_status[10];
static void * eNB_thread_rx(void *param) {

  //unsigned long cpuid;
  eNB_proc_t *proc = (eNB_proc_t*)param;
  //  RTIME time_in,time_out;
#ifdef RTAI
  RT_TASK *task;
982
  char task_name[8];
knopp's avatar
 
knopp committed
983 984 985 986 987 988 989 990
#endif

#if defined(ENABLE_ITTI)
  /* Wait for eNB application initialization to be complete (eNB registration to MME) */
  wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB);
#endif

#ifdef RTAI
991
  sprintf(task_name,"RXC%1dS%1d",proc->CC_id,proc->subframe);
knopp's avatar
 
knopp committed
992 993 994 995 996 997 998
  task = rt_task_init_schmod(nam2num(task_name), 0, 0, 0, SCHED_FIFO, 0xF);

  if (task==NULL) {
    LOG_E(PHY,"[SCHED][eNB] Problem starting eNB_proc_RX thread_index %d (%s)!!!!\n",proc->subframe,task_name);
    return 0;
  }
  else {
999 1000
    LOG_I(PHY,"[SCHED][eNB] eNB RX thread CC_id %d SF %d started with id %p\n", /*  on CPU %d*/
	  proc->CC_id,
knopp's avatar
 
knopp committed
1001
	  proc->subframe,
1002
	  task); /*,rtai_cpuid()*/
knopp's avatar
 
knopp committed
1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032
  }
#else
  LOG_I(PHY,"[SCHED][eNB] eNB RX thread %d started on CPU %d\n",
	proc->subframe,sched_getcpu());
#endif

  mlockall(MCL_CURRENT | MCL_FUTURE);

  //rt_set_runnable_on_cpuid(task,1);
  //cpuid = rtai_cpuid();

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

  while (!oai_exit){

    vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe),0);


    //    LOG_I(PHY,"Locking mutex for eNB proc %d (IC %d,mutex %p)\n",proc->subframe,proc->instance_cnt,&proc->mutex);
    if (pthread_mutex_lock(&proc->mutex_rx) != 0) {
      LOG_E(PHY,"[SCHED][eNB] error locking mutex for eNB RX proc %d\n",proc->subframe);
    }
    else {
        
      while (proc->instance_cnt_rx < 0) {
	//	LOG_I(PHY,"Waiting and unlocking mutex for eNB proc %d (IC %d,lock %d)\n",proc->subframe,proc->instance_cnt,pthread_mutex_trylock(&proc->mutex));

	pthread_cond_wait(&proc->cond_rx,&proc->mutex_rx);
knopp's avatar
 
knopp committed
1033
      }
knopp's avatar
 
knopp committed
1034 1035 1036
      //      LOG_I(PHY,"Waking up and unlocking mutex for eNB proc %d\n",proc->subframe);
      if (pthread_mutex_unlock(&proc->mutex_rx) != 0) {	
	LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for eNB RX proc %d\n",proc->subframe);
knopp's avatar
 
knopp committed
1037 1038
      }
    }
knopp's avatar
 
knopp committed
1039 1040 1041 1042
    vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe),1);    

    if (oai_exit) break;
    
knopp's avatar
 
knopp committed
1043 1044 1045
    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)) ||
	 (PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == FDD))){
      phy_procedures_eNB_RX(proc->subframe,PHY_vars_eNB_g[0][proc->CC_id],0,no_relay);
knopp's avatar
 
knopp committed
1046
    }
knopp's avatar
 
knopp committed
1047 1048
    if ((subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_rx)==SF_S)){
      phy_procedures_eNB_S_RX(proc->subframe,PHY_vars_eNB_g[0][proc->CC_id],0,no_relay);
knopp's avatar
 
knopp committed
1049 1050 1051 1052
    }
      
    if (pthread_mutex_lock(&proc->mutex_rx) != 0) {
      printf("[openair][SCHED][eNB] error locking mutex for eNB RX proc %d\n",proc->subframe);
knopp's avatar
 
knopp committed
1053 1054
    }
    else {
knopp's avatar
 
knopp committed
1055
      proc->instance_cnt_rx--;
knopp's avatar
 
knopp committed
1056
      
knopp's avatar
 
knopp committed
1057 1058
      if (pthread_mutex_unlock(&proc->mutex_rx) != 0) {	
	printf("[openair][SCHED][eNB] error unlocking mutex for eNB RX proc %d\n",proc->subframe);
knopp's avatar
 
knopp committed
1059 1060
      }
    }
knopp's avatar
 
knopp committed
1061 1062 1063 1064

    proc->frame_rx++;
    if (proc->frame_rx==1024)
      proc->frame_rx=0;
knopp's avatar
 
knopp committed
1065
    
knopp's avatar
 
knopp committed
1066 1067
  }
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe),0);        
knopp's avatar
 
knopp committed
1068
#ifdef HARD_RT
knopp's avatar
 
knopp committed
1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080
  rt_make_soft_real_time();
#endif

#ifdef DEBUG_THREADS
  printf("Exiting eNB thread RX %d\n",proc->subframe);
#endif
  // clean task
#ifdef RTAI
  rt_task_delete(task);
#else
  eNB_thread_rx_status[proc->subframe]=0;
  pthread_exit(&eNB_thread_rx_status[proc->subframe]);
knopp's avatar
 
knopp committed
1081 1082
#endif

knopp's avatar
 
knopp committed
1083 1084 1085
#ifdef DEBUG_THREADS
  printf("Exiting eNB RX thread %d\n",proc->subframe);
#endif
knopp's avatar
 
knopp committed
1086 1087 1088 1089
}



knopp's avatar
 
knopp committed
1090

1091
void init_eNB_proc(void) {
knopp's avatar
 
knopp committed
1092 1093

  int i;
knopp's avatar
 
knopp committed
1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123
  int CC_id;

  for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
    for (i=0;i<10;i++) {
      pthread_attr_init (&attr_eNB_proc_tx[CC_id][i]);
      pthread_attr_setstacksize(&attr_eNB_proc_tx[CC_id][i],OPENAIR_THREAD_STACK_SIZE);
      //attr_dlsch_threads.priority = 1;
      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);
      
      pthread_attr_init (&attr_eNB_proc_rx[CC_id][i]);
      pthread_attr_setstacksize(&attr_eNB_proc_rx[CC_id][i],OPENAIR_THREAD_STACK_SIZE);
      //attr_dlsch_threads.priority = 1;
      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);
      
	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;
	PHY_vars_eNB_g[0][CC_id]->proc[i].CC_id = CC_id;
	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);
	pthread_create(&PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_tx,NULL,eNB_thread_tx,(void*)&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,(void*)&PHY_vars_eNB_g[0][CC_id]->proc[i]);
	PHY_vars_eNB_g[0][CC_id]->proc[i].frame_tx = 0;
	PHY_vars_eNB_g[0][CC_id]->proc[i].frame_rx = 0;
knopp's avatar
 
knopp committed
1124
#ifndef USRP
knopp's avatar
 
knopp committed
1125 1126
	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;
knopp's avatar
 
knopp committed
1127
#else
knopp's avatar
 
knopp committed
1128 1129
	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;
knopp's avatar
 
knopp committed
1130
#endif
knopp's avatar
 
knopp committed
1131 1132 1133
    }
  
  
knopp's avatar
 
knopp committed
1134 1135
#ifndef USRP
  // TX processes subframe + 1, RX subframe -1
knopp's avatar
 
knopp committed
1136
  // 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
knopp's avatar
 
knopp committed
1137 1138 1139 1140
    
  //PHY_vars_eNB_g[0][CC_id]->proc[0].frame_rx = 1023;
    PHY_vars_eNB_g[0][CC_id]->proc[9].frame_tx = 1;
    PHY_vars_eNB_g[0][CC_id]->proc[0].frame_tx = 1;
knopp's avatar
 
knopp committed
1141
#else
knopp's avatar
 
knopp committed
1142 1143 1144 1145 1146
    // 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
    PHY_vars_eNB_g[0][CC_id]->proc[8].frame_tx = 1;
    PHY_vars_eNB_g[0][CC_id]->proc[9].frame_tx = 1;
    PHY_vars_eNB_g[0][CC_id]->proc[0].frame_tx = 1;
knopp's avatar
 
knopp committed
1147
#endif
knopp's avatar
 
knopp committed
1148 1149
  }
}
knopp's avatar
 
knopp committed
1150