lte-softmodem.c 101 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

knopp's avatar
 
knopp committed
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
#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>
51
#include <linux/sched.h>
52 53 54
#include <signal.h>
#include <execinfo.h>
#include <getopt.h>
55
#include <syscall.h>
56 57

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

60
#include "assertions.h"
61 62 63

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

#include "PHY/types.h"
68

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

knopp's avatar
knopp committed
73
#ifdef EXMIMO
74
#include "openair0_lib.h"
knopp's avatar
 
knopp committed
75 76 77 78
#else
#include "../../ARCH/COMMON/common_lib.h"
#endif

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

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

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

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

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

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

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

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

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

#define FRAME_PERIOD    100000000ULL
#define DAQ_PERIOD      66667ULL

Florian Kaltenberger's avatar
Florian Kaltenberger committed
137
//#define DEBUG_THREADS 1
knopp's avatar
 
knopp committed
138

knopp's avatar
 
knopp committed
139 140
//#define USRP_DEBUG 1

141 142 143 144 145 146 147 148
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;


knopp's avatar
 
knopp committed
149

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

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

157
void fill_ue_band_info(void);
158
#ifdef XFORMS
159 160 161 162
// 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];
163
FD_stats_form                  *form_stats=NULL,*form_stats_l2=NULL;
164
char title[255];
165
unsigned char                   scope_enb_num_ue = 1;
166 167 168
#endif //XFORMS

#ifdef RTAI
169

170 171
static long                      main_eNB_thread;
static long                      main_ue_thread;
172

173
#else
knopp's avatar
 
knopp committed
174 175
pthread_t                       main_eNB_thread;
pthread_t                       main_ue_thread;
176

177
pthread_attr_t                  attr_dlsch_threads;
178 179
pthread_attr_t                  attr_UE_thread;

180
#ifndef LOWLATENCY
181
struct sched_param              sched_param_dlsch;
182
#endif 
183
#endif
knopp's avatar
 
knopp committed
184

knopp's avatar
 
knopp committed
185 186
pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex;
187 188
int sync_var=-1;

189

190 191


192
struct sched_param              sched_param_UE_thread;
193

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

knopp's avatar
 
knopp committed
208
openair0_device openair0;
209

knopp's avatar
 
knopp committed
210

211
/*
knopp's avatar
 
knopp committed
212 213 214
  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;
215 216 217 218
*/
//extern unsigned int bigphys_top;
//extern unsigned int mem_base;

219
int                             card = 0;
knopp's avatar
 
knopp committed
220

221

222
#if defined(ENABLE_ITTI)
223 224
static volatile int             start_eNB = 0;
static volatile int             start_UE = 0;
225
#endif
226 227 228 229 230 231
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
232

233
static char                     UE_flag=0;
234 235
//static uint8_t                  eNB_id=0,UE_id=0;

236

237 238
uint32_t                 downlink_frequency[MAX_NUM_CCs][4];
int32_t                  uplink_frequency_offset[MAX_NUM_CCs][4]; 
gauthier's avatar
gauthier committed
239

240
openair0_rf_map rf_map[MAX_NUM_CCs];
241

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

247 248 249 250
int UE_scan = 1;
runmode_t mode = normal_txrx;


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

knopp's avatar
 
knopp committed
273 274
double sample_rate=30.72e6;
double bw = 14e6;
275

276
static int                      tx_max_power[MAX_NUM_CCs]; /* =  {0,0}*/;
277

knopp's avatar
knopp committed
278
#ifndef EXMIMO
knopp's avatar
 
knopp committed
279 280 281
char ref[128] = "internal";
char channels[128] = "0";

knopp's avatar
 
knopp committed
282 283
unsigned int samples_per_frame = 307200;
unsigned int tx_forward_nsamps;
knopp's avatar
 
knopp committed
284 285 286
int tx_delay;

#endif
287 288

int                      rx_input_level_dBm;
289
static int                      online_log_messages=0;
290
#ifdef XFORMS
291
extern int                      otg_enabled;
292
static char                     do_forms=0;
293
#else
294
int                             otg_enabled;
295
#endif
knopp's avatar
 
knopp committed
296
//int                             number_of_cards =   1;
knopp's avatar
 
knopp committed
297
#ifdef EXMIMO
298 299
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
300
#endif
301

knopp's avatar
 
knopp committed
302
static LTE_DL_FRAME_PARMS      *frame_parms[MAX_NUM_CCs];
303

knopp's avatar
 
knopp committed
304
int multi_thread=1;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
305
uint32_t target_dl_mcs = 28; //maximum allowed mcs
306
uint32_t target_ul_mcs = 10;
307 308
uint8_t exit_missed_slots=1;
uint64_t num_missed_slots=0; // counter for the number of missed slots
309

knopp's avatar
 
knopp committed
310

311
time_stats_t softmodem_stats_mt; // main thread
knopp's avatar
 
knopp committed
312
time_stats_t softmodem_stats_hw; //  hw acquisition
313 314
time_stats_t softmodem_stats_tx_sf[10]; // total tx time 
time_stats_t softmodem_stats_rx_sf[10]; // total rx time 
nikaeinn's avatar
nikaeinn committed
315 316
void reset_opp_meas(void);
void print_opp_meas(void);
317
int transmission_mode=1;
knopp's avatar
 
knopp committed
318

knopp's avatar
 
knopp committed
319

320
int16_t           glog_level         = LOG_INFO;
gauthier's avatar
 
gauthier committed
321
int16_t           glog_verbosity     = LOG_MED;
322
int16_t           hw_log_level       = LOG_INFO;
gauthier's avatar
 
gauthier committed
323
int16_t           hw_log_verbosity   = LOG_MED;
324
int16_t           phy_log_level      = LOG_INFO;
gauthier's avatar
 
gauthier committed
325
int16_t           phy_log_verbosity  = LOG_MED;
326
int16_t           mac_log_level      = LOG_INFO;
gauthier's avatar
 
gauthier committed
327
int16_t           mac_log_verbosity  = LOG_MED;
328
int16_t           rlc_log_level      = LOG_INFO;
gauthier's avatar
 
gauthier committed
329
int16_t           rlc_log_verbosity  = LOG_MED;
330
int16_t           pdcp_log_level     = LOG_INFO;
gauthier's avatar
 
gauthier committed
331
int16_t           pdcp_log_verbosity = LOG_MED;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
332
int16_t           rrc_log_level      = LOG_INFO;
gauthier's avatar
 
gauthier committed
333
int16_t           rrc_log_verbosity  = LOG_MED;
334 335 336
int16_t           opt_log_level      = LOG_INFO;
int16_t           opt_log_verbosity  = LOG_MED;

gauthier's avatar
 
gauthier committed
337 338 339 340 341 342
# 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
343 344 345 346
#if defined (ENABLE_SECURITY)
int16_t           osa_log_level      = LOG_INFO;
int16_t           osa_log_verbosity  = LOG_MED;
#endif 
347

knopp's avatar
 
knopp committed
348 349 350

#ifdef ETHERNET
char rrh_eNB_ip[20] = "127.0.0.1";
knopp's avatar
knopp committed
351
int rrh_eNB_port = 50000;
knopp's avatar
 
knopp committed
352
char *rrh_UE_ip = "127.0.0.1";
353
int rrh_UE_port = 51000;
knopp's avatar
 
knopp committed
354 355 356
#endif

char uecap_xer[1024],uecap_xer_in=0;
357 358
extern void *UE_thread(void *arg);
extern void init_UE_threads(void);
knopp's avatar
 
knopp committed
359

360
unsigned int build_rflocal(int txi, int txq, int rxi, int rxq)
361
{
knopp's avatar
 
knopp committed
362
  return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
363 364 365
}
unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe)
{
knopp's avatar
 
knopp committed
366
  return (dcoff_i_rxfe + (dcoff_q_rxfe<<8));
367 368
}

369 370 371 372 373 374 375 376 377 378 379 380
#ifdef LOWLATENCY
int sched_setattr(pid_t pid, const struct sched_attr *attr, unsigned int flags) {

  return syscall(__NR_sched_setattr, pid, attr, flags);
}


int sched_getattr(pid_t pid,struct sched_attr *attr,unsigned int size, unsigned int flags){

  return syscall(__NR_sched_getattr, pid, attr, size, flags);
}
#endif 
381
#if !defined(ENABLE_ITTI)
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
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 {
397
    printf("trying to exit gracefully...\n"); 
398
    oai_exit = 1;
399 400
  }
}
401
#endif
402 403 404

void exit_fun(const char* s)
{
405
  if (s != NULL) {
406
    printf("%s %s() Exiting OAI softmodem: %s\n",__FILE__, __FUNCTION__, s);
407 408 409 410 411
  }

  oai_exit = 1;

#if defined(ENABLE_ITTI)
Florian Kaltenberger's avatar
Florian Kaltenberger committed
412
  sleep(1); //allow lte-softmodem threads to exit first
413
  itti_terminate_tasks (TASK_UNKNOWN);
414
#endif
415 416 417 418 419 420

  //rt_sleep_ns(FRAME_PERIOD);

  //exit (-1);
}

knopp's avatar
 
knopp committed
421 422 423
static int latency_target_fd = -1;
static int32_t latency_target_value = 0;
/* Latency trick - taken from cyclictest.c 
knopp's avatar
 
knopp committed
424 425 426 427 428 429 430 431 432
 * 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
 */
knopp's avatar
 
knopp committed
433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449
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);
  }
}
knopp's avatar
 
knopp committed
450
 
451
#ifdef XFORMS
452 453 454 455

void reset_stats(FL_OBJECT *button, long arg) {
  int i,j,k;
  PHY_VARS_eNB *phy_vars_eNB = PHY_vars_eNB_g[0][0];
456 457 458 459 460 461 462 463 464 465 466 467
  for (i=0;i<NUMBER_OF_UE_MAX;i++) {
    for (k=0;k<8;k++) {//harq_processes
      for (j=0;j<phy_vars_eNB->dlsch_eNB[i][0]->Mdlharq;j++) {
	phy_vars_eNB->eNB_UE_stats[i].dlsch_NAK[k][j]=0;
	phy_vars_eNB->eNB_UE_stats[i].dlsch_ACK[k][j]=0;
	phy_vars_eNB->eNB_UE_stats[i].dlsch_trials[k][j]=0;
      }
      phy_vars_eNB->eNB_UE_stats[i].dlsch_l2_errors[k]=0;
      phy_vars_eNB->eNB_UE_stats[i].ulsch_errors[k]=0;
      phy_vars_eNB->eNB_UE_stats[i].ulsch_consecutive_errors=0;
      for (j=0;j<phy_vars_eNB->ulsch_eNB[i]->Mdlharq;j++) {
	phy_vars_eNB->eNB_UE_stats[i].ulsch_decoding_attempts[k][j]=0;
knopp's avatar
 
knopp committed
468 469 470
	phy_vars_eNB->eNB_UE_stats[i].ulsch_decoding_attempts_last[k][j]=0;
	phy_vars_eNB->eNB_UE_stats[i].ulsch_round_errors[k][j]=0;
	phy_vars_eNB->eNB_UE_stats[i].ulsch_round_fer[k][j]=0;
471
      }
472
    }
473 474 475
    phy_vars_eNB->eNB_UE_stats[i].dlsch_sliding_cnt=0;
    phy_vars_eNB->eNB_UE_stats[i].dlsch_NAK_round0=0;
    phy_vars_eNB->eNB_UE_stats[i].dlsch_mcs_offset=0;
476 477 478
  }
}

479
static void *scope_thread(void *arg) {
knopp's avatar
 
knopp committed
480
  char stats_buffer[16384];
481
# ifdef ENABLE_XFORMS_WRITE_STATS
knopp's avatar
 
knopp committed
482
  FILE *UE_stats, *eNB_stats;
483
# endif
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
484
  int len = 0;
knopp's avatar
 
knopp committed
485
  struct sched_param sched_param;
486
  int UE_id;
487

knopp's avatar
 
knopp committed
488 489
  sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1; 
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
490

knopp's avatar
 
knopp committed
491
  printf("Scope thread has priority %d\n",sched_param.sched_priority);
492
    
493 494
# ifdef ENABLE_XFORMS_WRITE_STATS
  if (UE_flag==1) 
knopp's avatar
 
knopp committed
495
    UE_stats  = fopen("UE_stats.txt", "w");
496
  else 
knopp's avatar
 
knopp committed
497
    eNB_stats = fopen("eNB_stats.txt", "w");
498
#endif
499
    
knopp's avatar
 
knopp committed
500 501
  while (!oai_exit) {
    if (UE_flag==1) {
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
502
      len = dump_ue_stats (PHY_vars_UE_g[0][0], stats_buffer, 0, mode,rx_input_level_dBm);
knopp's avatar
 
knopp committed
503
      fl_set_object_label(form_stats->stats_text, stats_buffer);
504

505 506 507 508
      phy_scope_UE(form_ue[0], 
		   PHY_vars_UE_g[0][0],
		   0,
		   0,7);
509
            
knopp's avatar
 
knopp committed
510
    } else {
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
511 512
#ifdef OPENAIR2
      len = dump_eNB_l2_stats (stats_buffer, 0);
513
      fl_set_object_label(form_stats_l2->stats_text, stats_buffer);
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
514 515 516 517 518
#endif
      len = dump_eNB_stats (PHY_vars_eNB_g[0][0], stats_buffer, 0);
      if (MAX_NUM_CCs>1)
	len += dump_eNB_stats (PHY_vars_eNB_g[0][1], &stats_buffer[len], 0);
    
519 520
      fl_set_object_label(form_stats->stats_text, stats_buffer);

knopp's avatar
 
knopp committed
521 522
      for(UE_id=0;UE_id<scope_enb_num_ue;UE_id++) {
	phy_scope_eNB(form_enb[UE_id], 
523
		      PHY_vars_eNB_g[0][0],
knopp's avatar
 
knopp committed
524 525
		      UE_id);
      }
526 527
              
    }
knopp's avatar
 
knopp committed
528
    //printf("doing forms\n");
Florian Kaltenberger's avatar
Florian Kaltenberger committed
529 530
    //usleep(100000); // 100 ms
    sleep(1);
knopp's avatar
 
knopp committed
531
  }
532 533

  printf("%s",stats_buffer);
534
    
535
# ifdef ENABLE_XFORMS_WRITE_STATS
536 537 538 539 540 541 542 543 544 545 546 547 548 549
  if (UE_flag==1) {
    if (UE_stats) {
      rewind (UE_stats);
      fwrite (stats_buffer, 1, len, UE_stats);
      fclose (UE_stats);
    }
  }
  else {
    if (eNB_stats) {
      rewind (eNB_stats);
      fwrite (stats_buffer, 1, len, eNB_stats);
      fclose (eNB_stats);
    }
  }
550
# endif
551
    
knopp's avatar
 
knopp committed
552
  pthread_exit((void*)arg);
553 554 555 556 557 558
}
#endif

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

jiangx's avatar
jiangx committed
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 590 591 592 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
void* gps_thread (void *arg)
{

  struct gps_data_t gps_data;
  struct gps_data_t *gps_data_ptr = &gps_data;
  struct sched_param sched_param;
  int ret;

  sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1; 
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
  
  printf("GPS thread has priority %d\n",sched_param.sched_priority);

  memset(&dummy_gps_data,0,sizeof(struct gps_fix_t));
  
#if GPSD_API_MAJOR_VERSION>=5
  ret = gps_open("127.0.0.1","2947",gps_data_ptr);
  if (ret!=0)
#else
  gps_data_ptr = gps_open("127.0.0.1","2947");
  if (gps_data_ptr == NULL) 
#endif
    {
      printf("[EMOS] Could not open GPS\n");
      pthread_exit((void*)arg);
    }
#if GPSD_API_MAJOR_VERSION>=4
  else if (gps_stream(gps_data_ptr, WATCH_ENABLE,NULL) != 0)
#else
  else if (gps_query(gps_data_ptr, "w+x") != 0)
#endif
    {
      printf("[EMOS] Error sending command to GPS\n");
      pthread_exit((void*) arg);
    }
  else 
    printf("[EMOS] Opened GPS, gps_data=%p\n", gps_data_ptr);
  

  while (!oai_exit)
    {
      printf("[EMOS] polling data from gps\n");
#if GPSD_API_MAJOR_VERSION>=5
      if (gps_waiting(gps_data_ptr,500)) {
	if (gps_read(gps_data_ptr) <= 0) {
#else
      if (gps_waiting(gps_data_ptr)) {
	if (gps_poll(gps_data_ptr) != 0) {
#endif
	  printf("[EMOS] problem polling data from gps\n");
	}
	else {
	  memcpy(&dummy_gps_data,&(gps_data_ptr->fix),sizeof(struct gps_fix_t));
	  printf("[EMOS] lat %g, lon %g\n",gps_data_ptr->fix.latitude,gps_data_ptr->fix.longitude);
	}
      } //gps_waiting
      else {
	printf("[EMOS] WARNING: No GPS data available, storing dummy packet\n");
      }
      //rt_sleep_ns(1000000000LL);
      sleep(1);
    } //oai_exit

  pthread_exit((void*) arg);

}

626 627 628 629 630 631 632 633 634 635 636 637
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;
  
jiangx's avatar
jiangx committed
638
  int channel_buffer_size,ret;
639 640 641 642
  
  time_t timer;
  struct tm *now;

643 644 645 646 647 648
  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);
649 650 651 652 653 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 687 688
 
  timer = time(NULL);
  now = localtime(&timer);

  if (UE_flag==0)
    channel_buffer_size = sizeof(fifo_dump_emos_eNB);
  else
    channel_buffer_size = sizeof(fifo_dump_emos_UE);

  // allocate memory for NO_FRAMES_DISK channes estimations
  fifo2file_buffer = malloc(NO_ESTIMATES_DISK*channel_buffer_size);
  fifo2file_ptr = fifo2file_buffer;

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


jiangx's avatar
jiangx committed
689
  printf("[EMOS] starting dump, channel_buffer_size=%d, fifo %d\n",channel_buffer_size,fifo);
690 691
  while (!oai_exit)
    {
jiangx's avatar
jiangx committed
692
      /*
693 694 695
      bytes = rtf_read_timed(fifo, fifo2file_ptr, channel_buffer_size,100);
      if (bytes==0)
	continue;
jiangx's avatar
jiangx committed
696 697 698 699 700 701 702 703 704
      */
      bytes = rtf_read_all_at_once(fifo, fifo2file_ptr, channel_buffer_size);
      if (bytes<=0) {
	usleep(100);
	continue;
      }
      if (bytes != channel_buffer_size) {
	printf("[EMOS] ERROR! Only got %d bytes instead of %d!\n",bytes,channel_buffer_size);
      }
705
      /*
jiangx's avatar
jiangx committed
706
      if (UE_flag==0)
707
	printf("eNB: count %d, frame %d, read: %d bytes from the fifo\n",counter, ((fifo_dump_emos_eNB*)fifo2file_ptr)->frame_tx,bytes);
jiangx's avatar
jiangx committed
708
      else
709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734
	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);
            }
jiangx's avatar
jiangx committed
735 736

	  if (fwrite(&dummy_gps_data, sizeof(char), sizeof(struct gps_fix_t), dumpfile_id) != sizeof(struct gps_fix_t))
737
	    {
jiangx's avatar
jiangx committed
738 739
	      printf("[EMOS] Error writing to dumpfile, stopping recording\n");
	      exit(EXIT_FAILURE);
740
	    }
jiangx's avatar
jiangx committed
741
	}
742 743 744 745 746 747 748 749 750 751 752
    }
  
  free(fifo2file_buffer);
  fclose(dumpfile_id);
  close(fifo);
  
  pthread_exit((void*) arg);

}
#endif

753 754


755
#if defined(ENABLE_ITTI)
756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773
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
774
#if defined(ENABLE_ITTI)
775
void *l2l1_task(void *arg)
776
{
knopp's avatar
 
knopp committed
777 778 779 780 781
  MessageDef *message_p = NULL;
  int         result;

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
782

knopp's avatar
 
knopp committed
783 784
  if (UE_flag == 0) {
    /* Wait for the initialize message */
785
    do {
knopp's avatar
 
knopp committed
786 787 788 789
      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);
      }
790 791 792
      itti_receive_msg (TASK_L2L1, &message_p);

      switch (ITTI_MSG_ID(message_p)) {
knopp's avatar
 
knopp committed
793 794 795 796 797 798 799
      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:
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
800
	printf("received terminate message\n");
knopp's avatar
 
knopp committed
801 802 803 804 805 806 807
	oai_exit=1;
	itti_exit_task ();
	break;

      default:
	LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
	break;
808
      }
knopp's avatar
 
knopp committed
809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830
    } 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;
831

knopp's avatar
 
knopp committed
832 833 834 835 836 837 838 839 840 841 842
    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
843
  } while(!oai_exit);
844

knopp's avatar
 
knopp committed
845
  return NULL;
846 847 848
}
#endif

knopp's avatar
 
knopp committed
849

knopp's avatar
 
knopp committed
850
void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) {
knopp's avatar
 
knopp committed
851 852 853 854

  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
855
  int slot_sizeF = (phy_vars_eNB->lte_frame_parms.ofdm_symbol_size)*
knopp's avatar
 
knopp committed
856
    ((phy_vars_eNB->lte_frame_parms.Ncp==1) ? 6 : 7);
knopp's avatar
 
knopp committed
857 858 859

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

knopp's avatar
 
knopp committed
862 863
  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
864
    //	  LOG_D(HW,"Frame %d: Generating slot %d\n",frame,next_slot);
knopp's avatar
 
knopp committed
865

knopp's avatar
 
knopp committed
866
    
knopp's avatar
 
knopp committed
867 868 869 870 871 872 873 874 875 876
    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
877 878 879 880 881 882 883 884
	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
885 886 887 888 889 890
      }
      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
891 892 893 894
	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
895
      }
knopp's avatar
 
knopp committed
896 897

      for (i=0; i<phy_vars_eNB->lte_frame_parms.samples_per_tti; i++) {
knopp's avatar
 
knopp committed
898 899 900 901 902 903
	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]=
knopp's avatar
 
knopp committed
904
#ifdef EXMIMO
knopp's avatar
 
knopp committed
905
	  ((short*)dummy_tx_b)[2*i]<<4;
knopp's avatar
 
knopp committed
906
#else
gauthier's avatar
gauthier committed
907
	  ((short*)dummy_tx_b)[2*i]<<5;
knopp's avatar
 
knopp committed
908
#endif
knopp's avatar
 
knopp committed
909
	((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[1]=
knopp's avatar
 
knopp committed
910
#ifdef EXMIMO
knopp's avatar
 
knopp committed
911
	  ((short*)dummy_tx_b)[2*i+1]<<4;
knopp's avatar
 
knopp committed
912
#else
gauthier's avatar
gauthier committed
913
	  ((short*)dummy_tx_b)[2*i+1]<<5;
knopp's avatar
 
knopp committed
914
#endif
knopp's avatar
 
knopp committed
915 916 917 918 919 920
      }
    }
  }
}


921 922 923 924 925 926 927 928 929
/*!
 * \brief The transmit thread of eNB.
 * \ref NUM_ENB_THREADS threads of this type are active at the same time.
 * \param param is a \ref eNB_proc_t structure which contains the info what to process.
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
static void* eNB_thread_tx( void* param )
{
  static int eNB_thread_tx_status[NUM_ENB_THREADS];
knopp's avatar
 
knopp committed
930 931

  eNB_proc_t *proc = (eNB_proc_t*)param;
932 933 934 935

  // set default return value
  eNB_thread_tx_status[proc->subframe] = 0;

knopp's avatar
 
knopp committed
936 937
#ifdef RTAI
  RT_TASK *task;
938
  char task_name[8];
knopp's avatar
 
knopp committed
939

940
  sprintf(task_name,"TXC%dS%d",proc->CC_id,proc->subframe);
knopp's avatar
 
knopp committed
941 942
  task = rt_task_init_schmod(nam2num(task_name), 0, 0, 0, SCHED_FIFO, 0xF);

943 944 945 946
  if (task == NULL) {
    LOG_E(PHY,"[SCHED][eNB] Problem starting eNB_proc_TX thread_index %d (%s)!!!!\n",proc->subframe,task_name);
    return 0;
  }
knopp's avatar
 
knopp committed
947
  else {
gauthier's avatar
gauthier committed
948 949 950 951 952
  LOG_I(PHY,"[SCHED][eNB] eNB TX thread CC %d SF %d started with id %p\n",
    proc->CC_id,
    proc->subframe,
    task);
}
knopp's avatar
 
knopp committed
953
#else
954
#ifdef LOWLATENCY
955 956 957
  struct sched_attr attr;
  unsigned int flags = 0;

958 959 960 961 962
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;
  
963 964 965
  // This creates a 1ms reservation every 10ms period
  attr.sched_policy   = SCHED_DEADLINE;
  attr.sched_runtime  = 0.9 *  1000000; // each tx thread requires 1ms to finish its job
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
966 967
  attr.sched_deadline = 1   *  1000000; // each tx thread will finish within 1ms
  attr.sched_period   = 1   * 10000000; // each tx thread has a period of 10ms from the starting point
968
  
969 970 971 972 973
  if (sched_setattr(0, &attr, flags) < 0 ) {
    perror("[SCHED] eNB tx thread: sched_setattr failed\n");
    return &eNB_thread_tx_status[proc->subframe];
  }
  LOG_I( HW, "[SCHED] eNB TX deadline thread %d(id %ld) started on CPU %d\n", proc->subframe, gettid(), sched_getcpu() );
974
#else 
975
  LOG_I( HW, "[SCHED][eNB] TX thread %d started on CPU %d\n", proc->subframe, sched_getcpu() );
976 977
#endif

knopp's avatar
 
knopp committed
978 979 980 981 982 983 984 985
#endif

  mlockall(MCL_CURRENT | MCL_FUTURE);

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

986
  while (!oai_exit) {
knopp's avatar
 
knopp committed
987
    
988
    vcd_signal_dumper_dump_function_by_name( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe), 0 );
knopp's avatar
 
knopp committed
989
    
knopp's avatar
knopp committed
990
    if (pthread_mutex_lock(&proc->mutex_tx) != 0) {
991
      LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc %d\n", proc->subframe );
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
992
      exit_fun("nothing to add");
993
      break;
knopp's avatar
knopp committed
994
    }
knopp's avatar
 
knopp committed
995
      
996
    while (proc->instance_cnt_tx < 0) {
997 998 999
      // most of the time the thread is waiting here
      // proc->instance_cnt_tx is -1
      pthread_cond_wait( &proc->cond_tx, &proc->mutex_tx ); // this unlocks mutex_tx while waiting and then locks it again
knopp's avatar
knopp committed
1000
    }
1001

1002 1003 1004 1005 1006
    if (pthread_mutex_unlock(&proc->mutex_tx) != 0) {
      LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for eNB TX proc %d\n",proc->subframe);
      exit_fun("nothing to add");
      break;
    }
knopp's avatar
 
knopp committed
1007

1008 1009 1010 1011 1012
    vcd_signal_dumper_dump_function_by_name( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe), 1 );
    vcd_signal_dumper_dump_variable_by_name( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX_ENB, proc->frame_tx );
    start_meas( &softmodem_stats_tx_sf[proc->subframe] );

    if (oai_exit) break;
knopp's avatar
 
knopp committed
1013
    
1014 1015 1016
    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))) {
ghaddab's avatar
ghaddab committed
1017

1018
      phy_procedures_eNB_TX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay, NULL );
knopp's avatar
 
knopp committed
1019
      
1020 1021 1022 1023
    }
    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
1024
    
1025
    do_OFDM_mod_rt( proc->subframe_tx, PHY_vars_eNB_g[0][proc->CC_id] );
knopp's avatar
 
knopp committed
1026
    
1027 1028 1029 1030 1031
    if (pthread_mutex_lock(&proc->mutex_tx) != 0) {
      LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc %d\n", proc->subframe );
      exit_fun("nothing to add");
      break;
    }
knopp's avatar
 
knopp committed
1032

1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048
    proc->instance_cnt_tx--;

    if (pthread_mutex_unlock(&proc->mutex_tx) != 0) {
      LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB TX proc %d\n", proc->subframe );
      exit_fun("nothing to add");
      break;
    }

    proc->frame_tx++;
    if (proc->frame_tx==1024)
      proc->frame_tx=0;

  }

  stop_meas( &softmodem_stats_tx_sf[proc->subframe] );
  vcd_signal_dumper_dump_function_by_name( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe), 0 );
knopp's avatar
 
knopp committed
1049

knopp's avatar
 
knopp committed
1050 1051 1052
#ifdef HARD_RT
  rt_make_soft_real_time