lte-enb.c 74 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.0  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62

/*! \file lte-enb.c
 * \brief Top-level threads for eNodeB
 * \author R. Knopp, F. Kaltenberger, Navid Nikaein
 * \date 2012
 * \version 0.1
 * \company Eurecom
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr
 * \note
 * \warning
 */
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sched.h>
#include <linux/sched.h>
#include <signal.h>
#include <execinfo.h>
#include <getopt.h>
#include <sys/sysinfo.h>
#include "rt_wrapper.h"

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

#include "assertions.h"
#include "msc.h"

#include "PHY/types.h"

#include "PHY/defs.h"
#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

#include "../../ARCH/COMMON/common_lib.h"

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

63
#include "PHY/LTE_TRANSPORT/if4_tools.h"
64
#include "PHY/LTE_TRANSPORT/if5_tools.h"
65

66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
#include "PHY/extern.h"
#include "SCHED/extern.h"
#include "LAYER2/MAC/extern.h"

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

#include "LAYER2/MAC/defs.h"
#include "LAYER2/MAC/extern.h"
#include "LAYER2/MAC/proto.h"
#include "RRC/LITE/extern.h"
#include "PHY_INTERFACE/extern.h"

#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_tx.h"
#include "UTIL/OTG/otg_externs.h"
#include "UTIL/MATH/oml.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
#include "UTIL/OPT/opt.h"
#include "enb_config.h"
//#include "PHY/TOOLS/time_meas.h"

#ifndef OPENAIR2
#include "UTIL/OTG/otg_extern.h"
#endif

#if defined(ENABLE_ITTI)
# if defined(ENABLE_USE_MME)
#   include "s1ap_eNB.h"
#ifdef PDCP_USE_NETLINK
#   include "SIMULATION/ETH_TRANSPORT/proto.h"
#endif
# endif
#endif

Rohit Gupta's avatar
Rohit Gupta committed
104 105
#include "T.h"

106 107 108 109 110 111 112 113 114 115
//#define DEBUG_THREADS 1

//#define USRP_DEBUG 1
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;

116 117
// Fix per CC openair rf/if device update
// extern openair0_device openair0;
118 119 120 121 122 123 124 125 126 127 128 129 130

#if defined(ENABLE_ITTI)
extern volatile int             start_eNB;
extern volatile int             start_UE;
#endif
extern volatile int                    oai_exit;

extern openair0_config_t openair0_cfg[MAX_CARDS];

extern pthread_cond_t sync_cond;
extern pthread_mutex_t sync_mutex;
extern int sync_var;

Cedric Roux's avatar
Cedric Roux committed
131
extern int transmission_mode;
132

133 134
extern int oaisim_flag;

135
//pthread_t                       main_eNB_thread;
136 137 138

time_stats_t softmodem_stats_mt; // main thread
time_stats_t softmodem_stats_hw; //  hw acquisition
139
time_stats_t softmodem_stats_rxtx_sf; // total tx time
140
time_stats_t softmodem_stats_rx_sf; // total rx time
141 142
//int32_t **rxdata;
//int32_t **txdata;
143

144 145
uint8_t seqno; //sequence number

146 147 148 149 150 151 152 153 154 155
static int                      time_offset[4] = {0,0,0,0};

/* mutex, cond and variable to serialize phy proc TX calls
 * (this mechanism may be relaxed in the future for better
 * performances)
 */
static struct {
  pthread_mutex_t  mutex_phy_proc_tx;
  pthread_cond_t   cond_phy_proc_tx;
  volatile uint8_t phy_proc_CC_id;
156
} sync_phy_proc;
157

158 159
extern double cpuf;

160 161
void exit_fun(const char* s);

162
void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst,eth_params_t *,int,int);
163
void stop_eNB(int nb_inst);
164 165


Raymond Knopp's avatar
Raymond Knopp committed
166
static inline void thread_top_init(char *thread_name,
167
				   int affinity,
Raymond Knopp's avatar
Raymond Knopp committed
168 169 170
				   uint64_t runtime,
				   uint64_t deadline,
				   uint64_t period) {
Raymond Knopp's avatar
Raymond Knopp committed
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190

  MSC_START_USE();

#ifdef DEADLINE_SCHEDULER
  struct sched_attr attr;

  unsigned int flags = 0;

  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;

  attr.sched_policy   = SCHED_DEADLINE;
  attr.sched_runtime  = runtime;
  attr.sched_deadline = deadline;
  attr.sched_period   = period; 

  if (sched_setattr(0, &attr, flags) < 0 ) {
    perror("[SCHED] eNB tx thread: sched_setattr failed\n");
laurent's avatar
laurent committed
191
    exit(1);
Raymond Knopp's avatar
Raymond Knopp committed
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
  }

#else //LOW_LATENCY
  int policy, s, j;
  struct sched_param sparam;
  char cpu_affinity[1024];
  cpu_set_t cpuset;

  /* Set affinity mask to include CPUs 1 to MAX_CPUS */
  /* CPU 0 is reserved for UHD threads */
  /* CPU 1 is reserved for all RX_TX threads */
  /* Enable CPU Affinity only if number of CPUs >2 */
  CPU_ZERO(&cpuset);

#ifdef CPU_AFFINITY
  if (get_nprocs() > 2)
  {
209 210 211 212
    if (affinity == 0)
      CPU_SET(0,&cpuset);
    else
      for (j = 1; j < get_nprocs(); j++)
Raymond Knopp's avatar
Raymond Knopp committed
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
        CPU_SET(j, &cpuset);
    s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
    if (s != 0)
    {
      perror( "pthread_setaffinity_np");
      exit_fun("Error setting processor affinity");
    }
  }
#endif //CPU_AFFINITY

  /* Check the actual affinity mask assigned to the thread */
  s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
  if (s != 0) {
    perror( "pthread_getaffinity_np");
    exit_fun("Error getting processor affinity ");
  }
  memset(cpu_affinity,0,sizeof(cpu_affinity));
  for (j = 0; j < CPU_SETSIZE; j++)
    if (CPU_ISSET(j, &cpuset)) {  
      char temp[1024];
      sprintf (temp, " CPU_%d", j);
      strcat(cpu_affinity, temp);
    }

  memset(&sparam, 0, sizeof(sparam));
238
  sparam.sched_priority = sched_get_priority_max(SCHED_FIFO);
Raymond Knopp's avatar
Raymond Knopp committed
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265
  policy = SCHED_FIFO ; 
  
  s = pthread_setschedparam(pthread_self(), policy, &sparam);
  if (s != 0) {
    perror("pthread_setschedparam : ");
    exit_fun("Error setting thread priority");
  }
  
  s = pthread_getschedparam(pthread_self(), &policy, &sparam);
  if (s != 0) {
    perror("pthread_getschedparam : ");
    exit_fun("Error getting thread priority");
  }

  LOG_I(HW, "[SCHED][eNB] %s started on CPU %d TID %ld, sched_policy = %s , priority = %d, CPU Affinity=%s \n",thread_name,sched_getcpu(),gettid(),
                   (policy == SCHED_FIFO)  ? "SCHED_FIFO" :
                   (policy == SCHED_RR)    ? "SCHED_RR" :
                   (policy == SCHED_OTHER) ? "SCHED_OTHER" :
                   "???",
                   sparam.sched_priority, cpu_affinity );

#endif //LOW_LATENCY

  mlockall(MCL_CURRENT | MCL_FUTURE);

}

Raymond Knopp's avatar
Raymond Knopp committed
266
static inline void wait_sync(char *thread_name) {
Raymond Knopp's avatar
Raymond Knopp committed
267 268 269 270 271 272 273 274 275 276 277 278 279

  printf( "waiting for sync (%s)\n",thread_name);
  pthread_mutex_lock( &sync_mutex );
  
  while (sync_var<0)
    pthread_cond_wait( &sync_cond, &sync_mutex );
  
  pthread_mutex_unlock(&sync_mutex);
  
  printf( "got sync (%s)\n", thread_name);

}

280 281 282 283

void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB)
{

284
  int CC_id = phy_vars_eNB->proc.CC_id;
285 286
  unsigned int aa,slot_offset;
  //int dummy_tx_b[7680*4] __attribute__((aligned(32)));
287
  int i, tx_offset;
288
  //int slot_sizeF = (phy_vars_eNB->frame_parms.ofdm_symbol_size)* ((phy_vars_eNB->frame_parms.Ncp==1) ? 6 : 7);
289
  int len;
290
  //int slot_offset_F = (subframe<<1)*slot_sizeF;
291

292
  slot_offset = subframe*phy_vars_eNB->frame_parms.samples_per_tti;
293

294 295
  if ((subframe_select(&phy_vars_eNB->frame_parms,subframe)==SF_DL)||
      ((subframe_select(&phy_vars_eNB->frame_parms,subframe)==SF_S))) {
296 297
    //    LOG_D(HW,"Frame %d: Generating slot %d\n",frame,next_slot);

298 299
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_OFDM_MODULATION,1);

300
    do_OFDM_mod_symbol(&phy_vars_eNB->common_vars,
301 302 303
		       0,
		       subframe<<1,
		       &phy_vars_eNB->frame_parms,
Florian Kaltenberger's avatar
Florian Kaltenberger committed
304
		       phy_vars_eNB->do_precoding);
305 306
 
    // if S-subframe generate first slot only 
307 308
    if (subframe_select(&phy_vars_eNB->frame_parms,subframe) == SF_DL) {
      do_OFDM_mod_symbol(&phy_vars_eNB->common_vars,
309 310 311
			 0,
			 1+(subframe<<1),
			 &phy_vars_eNB->frame_parms,
Florian Kaltenberger's avatar
Florian Kaltenberger committed
312
			 phy_vars_eNB->do_precoding);
313 314 315 316 317 318
    }

    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_OFDM_MODULATION,0);
    

/*
319 320 321
    for (aa=0; aa<phy_vars_eNB->frame_parms.nb_antennas_tx; aa++) {
      if (phy_vars_eNB->frame_parms.Ncp == EXTENDED) {
        PHY_ofdm_mod(&phy_vars_eNB->common_vars.txdataF[0][aa][slot_offset_F],
322
                     dummy_tx_b,
323
                     phy_vars_eNB->frame_parms.ofdm_symbol_size,
324
                     6,
325
                     phy_vars_eNB->frame_parms.nb_prefix_samples,
326
                     CYCLIC_PREFIX);
327 328 329 330 331 332 333
	if (subframe_select(&phy_vars_eNB->frame_parms,subframe) == SF_DL) 
	  PHY_ofdm_mod(&phy_vars_eNB->common_vars.txdataF[0][aa][slot_offset_F+slot_sizeF],
		       dummy_tx_b+(phy_vars_eNB->frame_parms.samples_per_tti>>1),
		       phy_vars_eNB->frame_parms.ofdm_symbol_size,
		       6,
		       phy_vars_eNB->frame_parms.nb_prefix_samples,
		       CYCLIC_PREFIX);
334
      } else {
335
        normal_prefix_mod(&phy_vars_eNB->common_vars.txdataF[0][aa][slot_offset_F],
336 337
                          dummy_tx_b,
                          7,
338
                          &(phy_vars_eNB->frame_parms));
339
	// if S-subframe generate first slot only
340 341 342
	if (subframe_select(&phy_vars_eNB->frame_parms,subframe) == SF_DL)
	  normal_prefix_mod(&phy_vars_eNB->common_vars.txdataF[0][aa][slot_offset_F+slot_sizeF],
			    dummy_tx_b+(phy_vars_eNB->frame_parms.samples_per_tti>>1),
343
			    7,
344
			    &(phy_vars_eNB->frame_parms));
345
      }
346
    } */
347

348
    for (aa=0; aa<phy_vars_eNB->frame_parms.nb_antennas_tx; aa++) {
349
      // if S-subframe generate first slot only
350 351
      if (subframe_select(&phy_vars_eNB->frame_parms,subframe) == SF_S)
	len = phy_vars_eNB->frame_parms.samples_per_tti>>1;
352
      else
353
	len = phy_vars_eNB->frame_parms.samples_per_tti;
354 355 356 357 358 359 360
      /*
      for (i=0;i<len;i+=4) {
	dummy_tx_b[i] = 0x100;
	dummy_tx_b[i+1] = 0x01000000;
	dummy_tx_b[i+2] = 0xff00;
	dummy_tx_b[i+3] = 0xff000000;
	}*/
361 362
      for (i=0; i<len; i++) {
        tx_offset = (int)slot_offset+time_offset[aa]+i;
363

364 365
	
        if (tx_offset<0)
366
          tx_offset += LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti;
367

368 369
        if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti))
          tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti;
370

371
/*	((short*)&phy_vars_eNB->common_vars.txdata[0][aa][tx_offset])[0] = ((short*)dummy_tx_b)[2*i]<<openair0_cfg[0].iq_txshift;
372
	
373
	((short*)&phy_vars_eNB->common_vars.txdata[0][aa][tx_offset])[1] = ((short*)dummy_tx_b)[2*i+1]<<openair0_cfg[0].iq_txshift; */
374

375
	((short*)&phy_vars_eNB->common_vars.txdata[0][aa][tx_offset])[0] = ((short*)&phy_vars_eNB->common_vars.txdata[0][aa][tx_offset])[0]<<openair0_cfg[CC_id].iq_txshift;
376
	
377
	((short*)&phy_vars_eNB->common_vars.txdata[0][aa][tx_offset])[1] = ((short*)&phy_vars_eNB->common_vars.txdata[0][aa][tx_offset])[1]<<openair0_cfg[CC_id].iq_txshift;
378
     }
379
     // if S-subframe switch to RX in second subframe
380
     if (subframe_select(&phy_vars_eNB->frame_parms,subframe) == SF_S) {
381
       for (i=0; i<len; i++) {
382
	 phy_vars_eNB->common_vars.txdata[0][aa][tx_offset++] = 0x00010001;
383 384
       }
     }
385

386 387 388 389
     if ((((phy_vars_eNB->frame_parms.tdd_config==0) ||
	  (phy_vars_eNB->frame_parms.tdd_config==1) ||
	  (phy_vars_eNB->frame_parms.tdd_config==2) ||
	  (phy_vars_eNB->frame_parms.tdd_config==6)) && 
390
	  (subframe==0)) || (subframe==5)) {
391 392 393
       // turn on tx switch N_TA_offset before
       //LOG_D(HW,"subframe %d, time to switch to tx (N_TA_offset %d, slot_offset %d) \n",subframe,phy_vars_eNB->N_TA_offset,slot_offset);
       for (i=0; i<phy_vars_eNB->N_TA_offset; i++) {
394
         tx_offset = (int)slot_offset+time_offset[aa]+i-phy_vars_eNB->N_TA_offset;
395 396
         if (tx_offset<0)
           tx_offset += LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti;
397
	 
398 399
	 if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti))
	   tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti;
400
	 
401
	 phy_vars_eNB->common_vars.txdata[0][aa][tx_offset] = 0x00000000;
402 403 404 405
       }
     }
    }
  }
406 407
}

408

409
void tx_fh_if5(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) {
410
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, proc->timestamp_tx&0xffffffff );
411 412 413
  if ((eNB->frame_parms.frame_type==FDD) ||
      ((eNB->frame_parms.frame_type==TDD) &&
       (subframe_select(&eNB->frame_parms,proc->subframe_tx) != SF_UL)))    
Raymond.Knopp's avatar
Raymond.Knopp committed
414
    send_IF5(eNB, proc->timestamp_tx, proc->subframe_tx, &seqno, IF5_RRH_GW_DL);
415 416
}

417 418
void tx_fh_if5_mobipass(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) {
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, proc->timestamp_tx&0xffffffff );
419 420 421
  if ((eNB->frame_parms.frame_type==FDD) ||
      ((eNB->frame_parms.frame_type==TDD) &&
       (subframe_select(&eNB->frame_parms,proc->subframe_tx) != SF_UL)))    
Raymond.Knopp's avatar
Raymond.Knopp committed
422
    send_IF5(eNB, proc->timestamp_tx, proc->subframe_tx, &seqno, IF5_MOBIPASS); 
423 424
}

Raymond.Knopp's avatar
Raymond.Knopp committed
425
void tx_fh_if4p5(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) {
426 427 428
  if ((eNB->frame_parms.frame_type==FDD) ||
      ((eNB->frame_parms.frame_type==TDD) &&
       (subframe_select(&eNB->frame_parms,proc->subframe_tx) != SF_UL)))    
Raymond.Knopp's avatar
Raymond.Knopp committed
429
    send_IF4p5(eNB,proc->frame_tx,proc->subframe_tx, IF4p5_PDLFFT, 0);
430 431
}

432 433 434 435
void proc_tx_high0(PHY_VARS_eNB *eNB,
		   eNB_rxtx_proc_t *proc,
		   relaying_type_t r_type,
		   PHY_VARS_RN *rn) {
436

Raymond Knopp's avatar
Raymond Knopp committed
437 438 439
  int offset = proc == &eNB->proc.proc_rxtx[0] ? 0 : 1;

  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_ENB+offset, proc->frame_tx );
440
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB+offset, proc->subframe_tx );
Raymond Knopp's avatar
Raymond Knopp committed
441

442
  phy_procedures_eNB_TX(eNB,proc,r_type,rn,1);
443 444 445 446 447 448 449 450 451 452 453 454 455 456

  /* we're done, let the next one proceed */
  if (pthread_mutex_lock(&sync_phy_proc.mutex_phy_proc_tx) != 0) {
    LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX proc\n");
    exit_fun("nothing to add");
  }	
  sync_phy_proc.phy_proc_CC_id++;
  sync_phy_proc.phy_proc_CC_id %= MAX_NUM_CCs;
  pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx);
  if (pthread_mutex_unlock(&sync_phy_proc.mutex_phy_proc_tx) != 0) {
    LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc\n");
    exit_fun("nothing to add");
  }

457 458 459 460 461 462
}

void proc_tx_high(PHY_VARS_eNB *eNB,
		  eNB_rxtx_proc_t *proc,
		  relaying_type_t r_type,
		  PHY_VARS_RN *rn) {
463

Raymond Knopp's avatar
Raymond Knopp committed
464

465 466 467 468 469 470 471 472 473 474 475 476
  // do PHY high
  proc_tx_high0(eNB,proc,r_type,rn);

  // if TX fronthaul go ahead 
  if (eNB->tx_fh) eNB->tx_fh(eNB,proc);

}

void proc_tx_full(PHY_VARS_eNB *eNB,
		  eNB_rxtx_proc_t *proc,
		  relaying_type_t r_type,
		  PHY_VARS_RN *rn) {
477

478 479 480 481 482 483

  // do PHY high
  proc_tx_high0(eNB,proc,r_type,rn);
  // do OFDM modulation
  do_OFDM_mod_rt(proc->subframe_tx,eNB);
  // if TX fronthaul go ahead 
484 485
  if (eNB->tx_fh) eNB->tx_fh(eNB,proc);

486 487 488 489 490 491 492 493 494 495 496
  /*
  if (proc->frame_tx>1000) {
    write_output("/tmp/txsig0.m","txs0", &eNB->common_vars.txdata[eNB->Mod_id][0][0], eNB->frame_parms.samples_per_tti*10,1,1);
    write_output("/tmp/txsigF0.m","txsF0", &eNB->common_vars.txdataF[eNB->Mod_id][0][0],eNB->frame_parms.symbols_per_tti*eNB->frame_parms.ofdm_symbol_size*10,1,1);
    write_output("/tmp/txsig1.m","txs1", &eNB->common_vars.txdata[eNB->Mod_id][1][0], eNB->frame_parms.samples_per_tti*10,1,1);
    write_output("/tmp/txsigF1.m","txsF1", &eNB->common_vars.txdataF[eNB->Mod_id][1][0],eNB->frame_parms.symbols_per_tti*eNB->frame_parms.ofdm_symbol_size*10,1,1);
    if (transmission_mode == 7) 
      write_output("/tmp/txsigF5.m","txsF5", &eNB->common_vars.txdataF[eNB->Mod_id][5][0],eNB->frame_parms.symbols_per_tti*eNB->frame_parms.ofdm_symbol_size*10,1,1);
    exit_fun("");
  }
  */
497 498
}

499 500 501 502
void proc_tx_rru_if4p5(PHY_VARS_eNB *eNB,
		       eNB_rxtx_proc_t *proc,
		       relaying_type_t r_type,
		       PHY_VARS_RN *rn) {
503 504 505 506 507

  uint32_t symbol_number=0;
  uint32_t symbol_mask, symbol_mask_full;
  uint16_t packet_type;

Raymond Knopp's avatar
Raymond Knopp committed
508 509 510
  int offset = proc == &eNB->proc.proc_rxtx[0] ? 0 : 1;

  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_ENB+offset, proc->frame_tx );
511
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB+offset, proc->subframe_tx );
Raymond Knopp's avatar
Raymond Knopp committed
512

513 514 515 516 517
  /// **** recv_IF4 of txdataF from RCC **** ///             
  symbol_number = 0;
  symbol_mask = 0;
  symbol_mask_full = (1<<eNB->frame_parms.symbols_per_tti)-1;
  
Raymond Knopp's avatar
Raymond Knopp committed
518

519 520 521 522 523 524 525 526 527
  do { 
    recv_IF4p5(eNB, &proc->frame_tx, &proc->subframe_tx, &packet_type, &symbol_number);
    symbol_mask = symbol_mask | (1<<symbol_number);
  } while (symbol_mask != symbol_mask_full); 

  do_OFDM_mod_rt(proc->subframe_tx, eNB);
}

void proc_tx_rru_if5(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) {
Raymond Knopp's avatar
Raymond Knopp committed
528 529 530
  int offset = proc == &eNB->proc.proc_rxtx[0] ? 0 : 1;

  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_ENB+offset, proc->frame_tx );
531
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB+offset, proc->subframe_tx );
532 533
  /// **** recv_IF5 of txdata from BBU **** ///       
  recv_IF5(eNB, &proc->timestamp_tx, proc->subframe_tx, IF5_RRH_GW_DL);
534 535
}

536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561
int wait_CCs(eNB_rxtx_proc_t *proc) {

  struct timespec wait;

  wait.tv_sec=0;
  wait.tv_nsec=5000000L;

  if (pthread_mutex_timedlock(&sync_phy_proc.mutex_phy_proc_tx,&wait) != 0) {
    LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX\n");
    exit_fun("nothing to add");
    return(-1);
  }
  
  // wait for our turn or oai_exit
  while (sync_phy_proc.phy_proc_CC_id != proc->CC_id && !oai_exit) {
    pthread_cond_wait(&sync_phy_proc.cond_phy_proc_tx,
		      &sync_phy_proc.mutex_phy_proc_tx);
  }
  
  if (pthread_mutex_unlock(&sync_phy_proc.mutex_phy_proc_tx) != 0) {
    LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX\n");
    exit_fun("nothing to add");
    return(-1);
  }
  return(0);
}
562

Raymond Knopp's avatar
Raymond Knopp committed
563 564 565
static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_name) {

  start_meas(&softmodem_stats_rxtx_sf);
566

Raymond Knopp's avatar
Raymond Knopp committed
567 568
  // ****************************************
  // Common RX procedures subframe n
569

570 571
  if ((eNB->do_prach)&&((eNB->node_function != NGFI_RCC_IF4p5)))
    eNB->do_prach(eNB,proc->frame_rx,proc->subframe_rx);
572
  phy_procedures_eNB_common_RX(eNB,proc);
Raymond Knopp's avatar
Raymond Knopp committed
573 574 575 576 577 578 579 580 581
  
  // UE-specific RX processing for subframe n
  if (eNB->proc_uespec_rx) eNB->proc_uespec_rx(eNB, proc, no_relay );
  
  // *****************************************
  // TX processing for subframe n+4
  // run PHY TX procedures the one after the other for all CCs to avoid race conditions
  // (may be relaxed in the future for performance reasons)
  // *****************************************
582
  //if (wait_CCs(proc)<0) return(-1);
Raymond Knopp's avatar
Raymond Knopp committed
583 584 585 586 587 588 589 590 591 592 593 594
  
  if (oai_exit) return(-1);
  
  if (eNB->proc_tx)	eNB->proc_tx(eNB, proc, no_relay, NULL );
  
  if (release_thread(&proc->mutex_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) return(-1);

  stop_meas( &softmodem_stats_rxtx_sf );
  
  return(0);
}

595
/*!
596
 * \brief The RX UE-specific and TX thread of eNB.
597 598 599
 * \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.
 */
600 601
static void* eNB_thread_rxtx( void* param ) {

602
  static int eNB_thread_rxtx_status;
603

604
  eNB_rxtx_proc_t *proc = (eNB_rxtx_proc_t*)param;
605 606
  PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id];

Raymond Knopp's avatar
Raymond Knopp committed
607 608
  char thread_name[100];

609

610
  // set default return value
611
  eNB_thread_rxtx_status = 0;
612 613


Raymond Knopp's avatar
Raymond Knopp committed
614
  sprintf(thread_name,"RXn_TXnp4_%d\n",&eNB->proc.proc_rxtx[0] == proc ? 0 : 1);
615
  thread_top_init(thread_name,1,850000L,1000000L,2000000L);
616 617

  while (!oai_exit) {
618
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 );
619

Raymond Knopp's avatar
Raymond Knopp committed
620
    if (wait_on_condition(&proc->mutex_rxtx,&proc->cond_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) break;
621

622
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 1 );
623

Raymond Knopp's avatar
Raymond Knopp committed
624
    
625
  
626 627
    if (oai_exit) break;

628 629
    if (eNB->CC_id==0)
      if (rxtx(eNB,proc,thread_name) < 0) break;
630

Raymond Knopp's avatar
Raymond Knopp committed
631
  } // while !oai_exit
632

633
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 );
634

Raymond Knopp's avatar
Raymond Knopp committed
635
  printf( "Exiting eNB thread RXn_TXnp4\n");
636

637 638
  eNB_thread_rxtx_status = 0;
  return &eNB_thread_rxtx_status;
639 640
}

641
#if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME)
642 643 644
/* Wait for eNB application initialization to be complete (eNB registration to MME) */
static void wait_system_ready (char *message, volatile int *start_flag) {
  
645
  static char *indicator[] = {".    ", "..   ", "...  ", ".... ", ".....",
646
			      " ....", "  ...", "   ..", "    .", "     "};
647 648 649 650 651 652 653
  int i = 0;
  
  while ((!oai_exit) && (*start_flag == 0)) {
    LOG_N(EMU, message, indicator[i]);
    fflush(stdout);
    i = (i + 1) % (sizeof(indicator) / sizeof(indicator[0]));
    usleep(200000);
654
  }
655 656
  
  LOG_D(EMU,"\n");
657 658
}
#endif
659

Raymond Knopp's avatar
Raymond Knopp committed
660

661
// asynchronous UL with IF5 (RCC,RAU,eNodeB_BBU)
Raymond Knopp's avatar
Raymond Knopp committed
662 663 664 665 666
void fh_if5_asynch_UL(PHY_VARS_eNB *eNB,int *frame,int *subframe) {

  eNB_proc_t *proc       = &eNB->proc;
  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;

667
  recv_IF5(eNB, &proc->timestamp_rx, *subframe, IF5_MOBIPASS); 
Raymond Knopp's avatar
Raymond Knopp committed
668

669 670 671 672 673 674 675
  int offset_mobipass = 40120;
  pthread_mutex_lock(&proc->mutex_asynch_rxtx);
  proc->subframe_rx = ((proc->timestamp_rx-offset_mobipass)/fp->samples_per_tti)%10;
  proc->frame_rx    = ((proc->timestamp_rx-offset_mobipass)/(fp->samples_per_tti*10))&1023;
  
  if (proc->first_rx == 1) {
    proc->first_rx =2;
Raymond Knopp's avatar
Raymond Knopp committed
676 677
    *subframe = proc->subframe_rx;
    *frame    = proc->frame_rx; 
678
    LOG_E(PHY,"[Mobipass]timestamp_rx:%llu, frame_rx %d, subframe: %d\n",proc->timestamp_rx,proc->frame_rx,proc->subframe_rx);
Raymond Knopp's avatar
Raymond Knopp committed
679 680 681
  }
  else {
    if (proc->subframe_rx != *subframe) {
682 683 684
        proc->first_rx++;
       LOG_E(PHY,"[Mobipass]timestamp:%llu, subframe_rx %d is not what we expect %d, first_rx:%d\n",proc->timestamp_rx, proc->subframe_rx,*subframe, proc->first_rx);
      //exit_fun("Exiting");
Raymond Knopp's avatar
Raymond Knopp committed
685 686
    }
    if (proc->frame_rx != *frame) {
687 688 689
        proc->first_rx++;
       LOG_E(PHY,"[Mobipass]timestamp:%llu, frame_rx %d is not what we expect %d, first_rx:%d\n",proc->timestamp_rx,proc->frame_rx,*frame, proc->first_rx);  
     // exit_fun("Exiting");
Raymond Knopp's avatar
Raymond Knopp committed
690
    }
691 692 693
    // temporary solution
      *subframe = proc->subframe_rx;
      *frame    = proc->frame_rx;
Raymond Knopp's avatar
Raymond Knopp committed
694
  }
695 696 697

  pthread_mutex_unlock(&proc->mutex_asynch_rxtx);

Raymond Knopp's avatar
Raymond Knopp committed
698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719
} // eNodeB_3GPP_BBU 

// asynchronous UL with IF4p5 (RCC,RAU,eNodeB_BBU)
void fh_if4p5_asynch_UL(PHY_VARS_eNB *eNB,int *frame,int *subframe) {

  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
  eNB_proc_t *proc       = &eNB->proc;

  uint16_t packet_type;
  uint32_t symbol_number,symbol_mask,symbol_mask_full,prach_rx;


  symbol_number = 0;
  symbol_mask = 0;
  symbol_mask_full = (1<<fp->symbols_per_tti)-1;
  prach_rx = 0;

  do {   // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!!
    recv_IF4p5(eNB, &proc->frame_rx, &proc->subframe_rx, &packet_type, &symbol_number);
    if (proc->first_rx != 0) {
      *frame = proc->frame_rx;
      *subframe = proc->subframe_rx;
720
      proc->first_rx--;
Raymond Knopp's avatar
Raymond Knopp committed
721 722 723
    }
    else {
      if (proc->frame_rx != *frame) {
724
	LOG_E(PHY,"fh_if4p5_asynch_UL: frame_rx %d is not what we expect %d\n",proc->frame_rx,*frame);
Raymond Knopp's avatar
Raymond Knopp committed
725 726 727
	exit_fun("Exiting");
      }
      if (proc->subframe_rx != *subframe) {
728
	LOG_E(PHY,"fh_if4p5_asynch_UL: subframe_rx %d is not what we expect %d\n",proc->subframe_rx,*subframe);
Raymond Knopp's avatar
Raymond Knopp committed
729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751
	exit_fun("Exiting");
      }
    }
    if (packet_type == IF4p5_PULFFT) {
      symbol_mask = symbol_mask | (1<<symbol_number);
      prach_rx = (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)>0) ? 1 : 0;                            
    } else if (packet_type == IF4p5_PRACH) {
      prach_rx = 0;
    }
  } while( (symbol_mask != symbol_mask_full) || (prach_rx == 1));    
  

} 


void fh_if5_asynch_DL(PHY_VARS_eNB *eNB,int *frame,int *subframe) {

  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
  eNB_proc_t *proc       = &eNB->proc;
  int subframe_tx,frame_tx;
  openair0_timestamp timestamp_tx;

  recv_IF5(eNB, &timestamp_tx, *subframe, IF5_RRH_GW_DL); 
Raymond Knopp's avatar
Raymond Knopp committed
752
  //printf("Received subframe %d (TS %llu) from RCC\n",subframe_tx,timestamp_tx);
Raymond Knopp's avatar
Raymond Knopp committed
753 754 755 756

  subframe_tx = (timestamp_tx/fp->samples_per_tti)%10;
  frame_tx    = (timestamp_tx/(fp->samples_per_tti*10))&1023;

757 758 759
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_ENB, frame_tx );
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB, subframe_tx );

Raymond Knopp's avatar
Raymond Knopp committed
760 761 762 763 764 765 766
  if (proc->first_tx != 0) {
    *subframe = subframe_tx;
    *frame    = frame_tx;
    proc->first_tx = 0;
  }
  else {
    if (subframe_tx != *subframe) {
767
      LOG_E(PHY,"fh_if5_asynch_DL: subframe_tx %d is not what we expect %d\n",subframe_tx,*subframe);
Raymond Knopp's avatar
Raymond Knopp committed
768 769 770
      exit_fun("Exiting");
    }
    if (frame_tx != *frame) { 
771
      LOG_E(PHY,"fh_if5_asynch_DL: frame_tx %d is not what we expect %d\n",frame_tx,*frame);
Raymond Knopp's avatar
Raymond Knopp committed
772 773 774 775 776 777 778 779 780 781 782
      exit_fun("Exiting");
    }
  }
}

void fh_if4p5_asynch_DL(PHY_VARS_eNB *eNB,int *frame,int *subframe) {

  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
  eNB_proc_t *proc       = &eNB->proc;

  uint16_t packet_type;
783
  uint32_t symbol_number,symbol_mask_full;
Raymond Knopp's avatar
Raymond Knopp committed
784 785 786 787
  int subframe_tx,frame_tx;

  symbol_number = 0;

Raymond Knopp's avatar
Raymond Knopp committed
788
  LOG_D(PHY,"fh_asynch_DL_IF4p5: in, frame %d, subframe %d\n",*frame,*subframe);
789 790 791 792 793 794 795 796 797 798 799

  // correct for TDD
  if (fp->frame_type == TDD) {
    while (subframe_select(fp,*subframe) == SF_UL) {
      *subframe=*subframe+1;
      if (*subframe==10) {
	*subframe=0;
	*frame=*frame+1;
      }
    }
  }
Raymond Knopp's avatar
Raymond Knopp committed
800 801 802

  LOG_D(PHY,"fh_asynch_DL_IF4p5: after TDD correction, frame %d, subframe %d\n",*frame,*subframe);

803
  symbol_mask_full = ((subframe_select(fp,*subframe) == SF_S) ? (1<<fp->dl_symbols_in_S_subframe) : (1<<fp->symbols_per_tti))-1;
Raymond Knopp's avatar
Raymond Knopp committed
804 805 806 807 808 809
  do {   // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!!
    recv_IF4p5(eNB, &frame_tx, &subframe_tx, &packet_type, &symbol_number);
    if (proc->first_tx != 0) {
      *frame    = frame_tx;
      *subframe = subframe_tx;
      proc->first_tx = 0;
810
      proc->frame_offset = frame_tx - proc->frame_tx;
Raymond Knopp's avatar
Raymond Knopp committed
811 812
      symbol_mask_full = ((subframe_select(fp,*subframe) == SF_S) ? (1<<fp->dl_symbols_in_S_subframe) : (1<<fp->symbols_per_tti))-1;

Raymond Knopp's avatar
Raymond Knopp committed
813 814 815
    }
    else {
      if (frame_tx != *frame) {
816
	LOG_E(PHY,"fh_if4p5_asynch_DL: frame_tx %d is not what we expect %d\n",frame_tx,*frame);
Raymond Knopp's avatar
Raymond Knopp committed
817 818 819
	exit_fun("Exiting");
      }
      if (subframe_tx != *subframe) {
820 821
	LOG_E(PHY,"fh_if4p5_asynch_DL: (frame %d) subframe_tx %d is not what we expect %d\n",frame_tx,subframe_tx,*subframe);
	//*subframe = subframe_tx;
Raymond Knopp's avatar
Raymond Knopp committed
822 823 824 825
	exit_fun("Exiting");
      }
    }
    if (packet_type == IF4p5_PDLFFT) {
826
      proc->symbol_mask[subframe_tx] =proc->symbol_mask[subframe_tx] | (1<<symbol_number);
Raymond Knopp's avatar
Raymond Knopp committed
827 828 829 830 831
    }
    else {
      LOG_E(PHY,"Illegal IF4p5 packet type (should only be IF4p5_PDLFFT%d\n",packet_type);
      exit_fun("Exiting");
    }
832 833
  } while (proc->symbol_mask[*subframe] != symbol_mask_full);    

834 835
  *frame = frame_tx;

836

837 838 839
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_ENB, frame_tx );
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB, subframe_tx );

840 841
  // intialize this to zero after we're done with the subframe
  proc->symbol_mask[*subframe] = 0;
Raymond Knopp's avatar
Raymond Knopp committed
842
  
843
  do_OFDM_mod_rt(*subframe, eNB);
Raymond Knopp's avatar
Raymond Knopp committed
844 845
} 

846
/*!
847
 * \brief The Asynchronous RX/TX FH thread of RAU/RCC/eNB/RRU.
848 849 850 851
 * This handles the RX FH for an asynchronous RRU/UE
 * \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.
 */
852
static void* eNB_thread_asynch_rxtx( void* param ) {
853

854
  static int eNB_thread_asynch_rxtx_status;
855

856 857
  eNB_proc_t *proc = (eNB_proc_t*)param;
  PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id];
Raymond Knopp's avatar
Raymond Knopp committed
858 859


860

Raymond Knopp's avatar
Raymond Knopp committed
861
  int subframe=0, frame=0; 
862

863
  thread_top_init("thread_asynch",1,870000L,1000000L,1000000L);
864 865 866

  // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe

Raymond Knopp's avatar
Raymond Knopp committed
867
  wait_sync("thread_asynch");
868 869 870 871

  // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe
  printf( "waiting for devices (eNB_thread_asynch_rx)\n");

Raymond Knopp's avatar
Raymond Knopp committed
872
  wait_on_condition(&proc->mutex_asynch_rxtx,&proc->cond_asynch_rxtx,&proc->instance_cnt_asynch_rxtx,"thread_asynch");
873 874 875 876

  printf( "devices ok (eNB_thread_asynch_rx)\n");


Raymond Knopp's avatar
Raymond Knopp committed
877 878 879
  while (!oai_exit) { 
   
    if (oai_exit) break;   
880

Raymond Knopp's avatar
Raymond Knopp committed
881 882 883 884 885 886 887
    if (subframe==9) { 
      subframe=0;
      frame++;
      frame&=1023;
    } else {
      subframe++;
    }      
888

Raymond Knopp's avatar
Raymond Knopp committed
889 890 891
    if (eNB->fh_asynch) eNB->fh_asynch(eNB,&frame,&subframe);
    else AssertFatal(1==0, "Unknown eNB->node_function %d",eNB->node_function);
    
892
  }
Raymond Knopp's avatar
Raymond Knopp committed
893

894 895
  eNB_thread_asynch_rxtx_status=0;
  return(&eNB_thread_asynch_rxtx_status);
896
}
897

898

Raymond Knopp's avatar
Raymond Knopp committed
899 900 901 902 903 904



void rx_rf(PHY_VARS_eNB *eNB,int *frame,int *subframe) {

  eNB_proc_t *proc = &eNB->proc;
905 906 907 908
  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
  void *rxp[fp->nb_antennas_rx],*txp[fp->nb_antennas_tx]; 
  unsigned int rxs,txs;
  int i;
909
  int tx_sfoffset = (eNB->single_thread_flag == 1) ? 3 : 2;
910
  openair0_timestamp ts,old_ts;
911

912 913
  if (proc->first_rx==0) {
    
914
    // Transmit TX buffer based on timestamp from RX
915
    //    printf("trx_write -> USRP TS %llu (sf %d)\n", (proc->timestamp_rx+(3*fp->samples_per_tti)),(proc->subframe_rx+2)%10);
916
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (proc->timestamp_rx+(tx_sfoffset*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance)&0xffffffff );
917
    // prepare tx buffer pointers
918 919 920 921 922 923

    lte_subframe_t SF_type     = subframe_select(fp,(proc->subframe_rx+tx_sfoffset)%10);
    lte_subframe_t prevSF_type = subframe_select(fp,(proc->subframe_rx+tx_sfoffset+9)%10);
    lte_subframe_t nextSF_type = subframe_select(fp,(proc->subframe_rx+tx_sfoffset+1)%10);
    if ((SF_type == SF_DL) ||
	(SF_type == SF_S)) {
924 925 926

      for (i=0; i<fp->nb_antennas_tx; i++)
	txp[i] = (void*)&eNB->common_vars.txdata[0][i][((proc->subframe_rx+tx_sfoffset)%10)*fp->samples_per_tti]; 
927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947

      int siglen=fp->samples_per_tti,flags=1;

      if (SF_type == SF_S) {
	siglen = fp->dl_symbols_in_S_subframe*(fp->ofdm_symbol_size+fp->nb_prefix_samples0);
	flags=3; // end of burst
      }
      if ((fp->frame_type == TDD) &&
	  (SF_type == SF_DL)&&
	  (prevSF_type == SF_UL) &&
	  (nextSF_type == SF_DL))
	flags = 2; // start of burst

      if ((fp->frame_type == TDD) &&
	  (SF_type == SF_DL)&&
	  (prevSF_type == SF_UL) &&
	  (nextSF_type == SF_UL))
	flags = 4; // start of burst and end of burst (only one DL SF between two UL)
     
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_WRITE_FLAGS,flags); 
948 949 950
      txs = eNB->rfdevice.trx_write_func(&eNB->rfdevice,
					 proc->timestamp_rx+eNB->ts_offset+(tx_sfoffset*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance,
					 txp,
951
					 siglen,
952
					 fp->nb_antennas_tx,
953
					 flags);
954 955 956 957 958
      
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
      
      
      
959
      if (txs !=  siglen) {
960 961 962 963
	LOG_E(PHY,"TX : Timeout (sent %d/%d)\n",txs, fp->samples_per_tti);
	exit_fun( "problem transmitting samples" );
      }	
    }
964
  }
965

966 967 968 969
  for (i=0; i<fp->nb_antennas_rx; i++)
    rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][*subframe*fp->samples_per_tti];
  
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 );
970

971 972
  old_ts = proc->timestamp_rx;

973
  rxs = eNB->rfdevice.trx_read_func(&eNB->rfdevice,
974
				    &ts,
975 976 977
				    rxp,
				    fp->samples_per_tti,
				    fp->nb_antennas_rx);
978

979 980
  proc->timestamp_rx = ts-eNB->ts_offset;

981
  if (rxs != fp->samples_per_tti)
982
    LOG_E(PHY,"rx_rf: Asked for %d samples, got %d from USRP\n",fp->samples_per_tti,rxs);
983

984
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
Raymond Knopp's avatar
Raymond Knopp committed
985
 
986
  if (proc->first_rx == 1) {
Raymond Knopp's avatar
Raymond Knopp committed
987
    eNB->ts_offset = proc->timestamp_rx;
988 989
    proc->timestamp_rx=0;
  }
990
  else {
991

992
    if (proc->timestamp_rx - old_ts != fp->samples_per_tti) {
993 994
      LOG_I(PHY,"rx_rf: rfdevice timing drift of %d samples\n",proc->timestamp_rx - old_ts - fp->samples_per_tti);
      eNB->ts_offset += (proc->timestamp_rx - old_ts - fp->samples_per_tti);
995
      proc->timestamp_rx = ts-eNB->ts_offset;
996 997
    }
  }
998 999
  proc->frame_rx    = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023;
  proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10;
1000
  proc->frame_rx    = (proc->frame_rx+proc->frame_offset)&1023;
1001
  proc->frame_tx    = proc->frame_rx;
1002
  if (proc->subframe_rx > 5) proc->frame_tx=(proc->frame_tx+1)&1023;
1003 1004
  // synchronize first reception to frame 0 subframe 0

1005
  proc->timestamp_tx = proc->timestamp_rx+(4*fp->samples_per_tti);
1006
  //  printf("trx_read <- USRP TS %lu (offset %d sf %d, f %d, first_rx %d)\n", proc->timestamp_rx,eNB->ts_offset,proc->subframe_rx,proc->frame_rx,proc->first_rx);  
1007 1008 1009
  
  if (proc->first_rx == 0) {
    if (proc->subframe_rx != *subframe){
1010
      LOG_E(PHY,"rx_rf: Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->timestamp_rx,proc->subframe_rx,*subframe);
1011 1012
      exit_fun("Exiting");
    }
1013
    int f2 = (*frame+proc->frame_offset)&1023;    
1014
    if (proc->frame_rx != f2) {
1015
      LOG_E(PHY,"rx_rf: Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->frame_rx %d frame %d, frame_offset %d, f2 %d)\n",proc->timestamp_rx,proc->frame_rx,*frame,proc->frame_offset,f2);
1016 1017 1018
      exit_fun("Exiting");
    }
  } else {
1019
    proc->first_rx--;
1020 1021 1022 1023 1024 1025 1026 1027
    *frame = proc->frame_rx;
    *subframe = proc->subframe_rx;        
  }
  
  //printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",proc->timestamp_rx,proc->frame_rx,frame,proc->subframe_rx,subframe);
  
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
  
1028 1029 1030 1031 1032
  if (rxs != fp->samples_per_tti)
    exit_fun( "problem receiving samples" );
  

  
1033 1034
}

Raymond Knopp's avatar
Raymond Knopp committed
1035
void rx_fh_if5(PHY_VARS_eNB *eNB,int *frame, int *subframe) {
1036 1037

  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
Raymond Knopp's avatar
Raymond Knopp committed
1038
  eNB_proc_t *proc = &eNB->proc;
1039 1040 1041 1042 1043 1044 1045

  recv_IF5(eNB, &proc->timestamp_rx, *subframe, IF5_RRH_GW_UL); 

  proc->frame_rx    = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023;
  proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10;
  
  if (proc->first_rx == 0) {
1046
    if (proc->subframe_rx != *subframe){
1047
      LOG_E(PHY,"rx_fh_if5: Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,*subframe);
1048 1049 1050
      exit_fun("Exiting");
    }
    
1051
    if (proc->frame_rx != *frame) {
1052
      LOG_E(PHY,"rx_fh_if5: Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,*frame);
1053 1054 1055
      exit_fun("Exiting");
    }
  } else {
1056
    proc->first_rx--;
1057 1058
    *frame = proc->frame_rx;
    *subframe = proc->subframe_rx;        
1059
  }      
Raymond.Knopp's avatar
Raymond.Knopp committed
1060

1061 1062


Raymond.Knopp's avatar
Raymond.Knopp committed
1063
  proc->timestamp_tx = proc->timestamp_rx +  (4*fp->samples_per_tti);
1064 1065 1066 1067 1068
  
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );

}

Raymond Knopp's avatar
Raymond Knopp committed
1069

1070
void rx_fh_if4p5(PHY_VARS_eNB *eNB,int *frame,int *subframe) {
1071 1072

  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
1073
  eNB_proc_t *proc = &eNB->proc;
1074
  int f,sf;
1075 1076 1077

  uint16_t packet_type;
  uint32_t symbol_number=0;
Raymond.Knopp's avatar
Raymond.Knopp committed
1078
  uint32_t symbol_mask_full;
1079

1080 1081 1082 1083
  if ((fp->frame_type == TDD) && (subframe_select(fp,*subframe)==SF_S))
    symbol_mask_full = (1<<fp->ul_symbols_in_S_subframe)-1;
  else 
    symbol_mask_full = (1<<fp->symbols_per_tti)-1;
1084

1085
  if (eNB->CC_id==1) LOG_I(PHY,"rx_fh_if4p5: frame %d, subframe %d\n",*frame,*subframe);
1086
  do {   // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!!
1087
    recv_IF4p5(eNB, &f, &sf, &packet_type, &symbol_number);
1088

1089
    //proc->frame_rx = (proc->frame_rx + proc->frame_offset)&1023;
1090
    if (packet_type == IF4p5_PULFFT) {
Raymond Knopp's avatar
Raymond Knopp committed
1091
      LOG_D(PHY,"rx_fh_if4p5: frame %d, subframe %d, PULFFT symbol %d\n",f,sf,symbol_number);
1092

Raymond.Knopp's avatar
Raymond.Knopp committed
1093
      proc->symbol_mask[sf] = proc->symbol_mask[sf] | (1<<symbol_number);
1094
    } else if (packet_type == IF4p5_PULTICK) {
1095 1096
    
      if ((proc->first_rx==0) && (f!=*frame))
Raymond Knopp's avatar
Raymond Knopp committed
1097
	LOG_E(PHY,"rx_fh_if4p5: PULTICK received frame %d != expected %d\n",f,*frame);
1098 1099
      if ((proc->first_rx==0) && (sf!=*subframe))
	LOG_E(PHY,"rx_fh_if4p5: PULTICK received subframe %d != expected %d (first_rx %d)\n",sf,*subframe,proc->first_rx);
Raymond Knopp's avatar
Raymond Knopp committed
1100
      break;
1101
    } else if (packet_type == IF4p5_PRACH) {
1102
      LOG_D(PHY,"rx_fh:if4p5: frame %d, subframe %d, PRACH\n",f,sf);
1103 1104
      // wakeup prach processing
      if (eNB->do_prach) eNB->do_prach(eNB,f,sf);
1105
    }
1106

1107
    if (eNB->CC_id==1) LOG_I(PHY,"rx_fh_if4p5: symbol_mask[%d] %x\n",*subframe,proc->symbol_mask[*subframe]);
1108

1109
  } while(proc->symbol_mask[*subframe] != symbol_mask_full);    
1110 1111 1112

  proc->subframe_rx = sf;
  proc->frame_rx    = f;
Raymond.Knopp's avatar
Raymond.Knopp committed
1113

1114 1115 1116 1117
  proc->symbol_mask[*subframe] = 0;
  proc->symbol_mask[(9+*subframe)%10]= 0; // to handle a resynchronization event

  if (eNB->CC_id==1) LOG_I(PHY,"Clearing symbol_mask[%d]\n",*subframe);
1118 1119

  //caculate timestamp_rx, timestamp_tx based on frame and subframe
1120 1121 1122
  proc->timestamp_rx = ((proc->frame_rx * 10)  + proc->subframe_rx ) * fp->samples_per_tti ;
  proc->timestamp_tx = proc->timestamp_rx +  (4*fp->samples_per_tti);
  
1123
 
1124 1125
  if (proc->first_rx == 0) {
    if (proc->subframe_rx != *subframe){
1126
      LOG_E(PHY,"rx_fh_if4p5, CC_id %d: Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d,CCid %d)\n",eNB->CC_id,proc->subframe_rx,*subframe,eNB->CC_id);
1127 1128
    }
    if (proc->frame_rx != *frame) {
1129 1130 1131 1132
      if (proc->frame_rx == proc->frame_offset) // This means that the RRU has adjusted its frame timing
	proc->frame_offset = 0;
      else 
	LOG_E(PHY,"rx_fh_if4p5: Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d,CCid %d)\n",proc->frame_rx,*frame,eNB->CC_id);
1133 1134 1135
    }
  } else {
    proc->first_rx = 0;
1136 1137 1138 1139 1140
    if (eNB->CC_id==0)
      proc->frame_offset = 0;
    else
      proc->frame_offset = PHY_vars_eNB_g[0][0]->proc.frame_rx;

1141
    *frame = proc->frame_rx;//(proc->frame_rx + proc->frame_offset)&1023;
1142 1143 1144
    *subframe = proc->subframe_rx;        
  }
  
1145 1146 1147


  if (eNB->CC_id==0) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
1148 1149 1150
  
}

Raymond Knopp's avatar
Raymond Knopp committed
1151 1152
void rx_fh_slave(PHY_VARS_eNB *eNB,int *frame,int *subframe) {
  // This case is for synchronization to another thread
1153
  // it just waits for an external event.  The actual rx_fh is handle by the asynchronous RX thread
Raymond Knopp's avatar
Raymond Knopp committed
1154 1155
  eNB_proc_t *proc=&eNB->proc;

Raymond Knopp's avatar
Raymond Knopp committed
1156 1157 1158 1159 1160
  if (wait_on_condition(&proc->mutex_FH,&proc->cond_FH,&proc->instance_cnt_FH,"rx_fh_slave") < 0)
    return;

  release_thread(&proc->mutex_FH,&proc->instance_cnt_FH,"rx_fh_slave");

Raymond Knopp's avatar
Raymond Knopp committed
1161 1162 1163 1164
  
}


1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196
int wakeup_rxtx(eNB_proc_t *proc,eNB_rxtx_proc_t *proc_rxtx,LTE_DL_FRAME_PARMS *fp) {

  int i;
  struct timespec wait;
  
  wait.tv_sec=0;
  wait.tv_nsec=5000000L;

  /* accept some delay in processing - up to 5ms */
  for (i = 0; i < 10 && proc_rxtx->instance_cnt_rxtx == 0; i++) {
    LOG_W( PHY,"[eNB] Frame %d, eNB RXn-TXnp4 thread busy!! (cnt_rxtx %i)\n", proc_rxtx->frame_tx, proc_rxtx->instance_cnt_rxtx);
    usleep(500);
  }
  if (proc_rxtx->instance_cnt_rxtx == 0) {
    exit_fun( "TX thread busy" );
    return(-1);
  }

  // wake up TX for subframe n+4
  // lock the TX mutex and make sure the thread is ready
  if (pthread_mutex_timedlock(&proc_rxtx->mutex_rxtx,&wait) != 0) {
    LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB RXTX thread %d (IC %d)\n", proc_rxtx->subframe_rx&1,proc_rxtx->instance_cnt_rxtx );
    exit_fun( "error locking mutex_rxtx" );
    return(-1);
  }
  
  ++proc_rxtx->instance_cnt_rxtx;
  
  // We have just received and processed the common part of a subframe, say n. 
  // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired 
  // transmitted timestamp of the next TX slot (first).
  // The last (TS_rx mod samples_per_frame) was n*samples_per_tti, 
Raymond Knopp's avatar
Raymond Knopp committed
1197 1198
  // we want to generate subframe (n+4), so TS_tx = TX_rx+4*samples_per_tti,
  // and proc->subframe_tx = proc->subframe_rx+4
1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229
  proc_rxtx->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_tti);
  proc_rxtx->frame_rx     = proc->frame_rx;
  proc_rxtx->subframe_rx  = proc->subframe_rx;
  proc_rxtx->frame_tx     = (proc_rxtx->subframe_rx > 5) ? (proc_rxtx->frame_rx+1)&1023 : proc_rxtx->frame_rx;
  proc_rxtx->subframe_tx  = (proc_rxtx->subframe_rx + 4)%10;
  
  // the thread can now be woken up
  if (pthread_cond_signal(&proc_rxtx->cond_rxtx) != 0) {
    LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB RXn-TXnp4 thread\n");
    exit_fun( "ERROR pthread_cond_signal" );
    return(-1);
  }
  
  pthread_mutex_unlock( &proc_rxtx->mutex_rxtx );

  return(0);
}

void wakeup_slaves(eNB_proc_t *proc) {

  int i;
  struct timespec wait;
  
  wait.tv_sec=0;
  wait.tv_nsec=5000000L;
  
  for (i=0;i<proc->num_slaves;i++) {
    eNB_proc_t *slave_proc = proc->slave_proc[i];
    // wake up slave FH thread
    // lock the FH mutex and make sure the thread is ready
    if (pthread_mutex_timedlock(&slave_proc->mutex_FH,&wait) != 0) {
Cedric Roux's avatar
Cedric Roux committed
1230 1231 1232
      /* TODO: fix this log, what is 'IC'? */
      /*LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB CCid %d slave CCid %d (IC %d)\n",proc->CC_id,slave_proc->CC_id);*/
      LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB CCid %d slave CCid %d\n",proc->CC_id,slave_proc->CC_id);
1233 1234 1235
      exit_fun( "error locking mutex_rxtx" );
      break;
    }
1236 1237 1238 1239 1240 1241
   
    while (slave_proc->instance_cnt_FH == 0) {
     // LOG_W( PHY,"[eNB] Frame:%d , eNB rx_fh_slave thread busy!! (cnt_FH %i)\n", proc->frame_rx,slave_proc->instance_cnt_FH );
      usleep(500);
    } 

1242 1243 1244
    int cnt_slave            = ++slave_proc->instance_cnt_FH;
    slave_proc->frame_rx     = proc->frame_rx;
    slave_proc->subframe_rx  = proc->subframe_rx;
1245
    //slave_proc->timestamp_rx = proc->timestamp_rx;
1246 1247
    slave_proc->timestamp_tx = proc->timestamp_tx; 

1248 1249 1250 1251 1252 1253 1254 1255 1256 1257
    pthread_mutex_unlock( &slave_proc->mutex_FH );
    
    if (cnt_slave == 0) {
      // the thread was presumably waiting where it should and can now be woken up
      if (pthread_cond_signal(&slave_proc->cond_FH) != 0) {
	LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB CCid %d, slave CCid %d\n",proc->CC_id,slave_proc->CC_id);
          exit_fun( "ERROR pthread_cond_signal" );
	  break;
      }
    } else {
1258
      LOG_W( PHY,"[eNB] Frame %d, slave CC_id %d thread busy!! (cnt_FH %i)\n",slave_proc->frame_rx,slave_proc->CC_id, cnt_slave);
1259 1260 1261 1262 1263 1264
      exit_fun( "FH thread busy" );
      break;
    }             
  }
}

1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323
uint32_t sync_corr[307200] __attribute__((aligned(32)));

// This thread run the initial synchronization like a UE
void *eNB_thread_synch(void *arg) {

  PHY_VARS_eNB *eNB = (PHY_VARS_eNB*)arg;
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
  int32_t sync_pos,sync_pos2;
  uint32_t peak_val;

  thread_top_init("eNB_thread_synch",0,5000000,10000000,10000000);

  wait_sync("eNB_thread_synch");

  // initialize variables for PSS detection
  lte_sync_time_init(&eNB->frame_parms);

  while (!oai_exit) {

    // wait to be woken up
    pthread_mutex_lock(&eNB->proc.mutex_synch);
    while (eNB->proc.instance_cnt_synch < 0)
      pthread_cond_wait(&eNB->proc.cond_synch,&eNB->proc.mutex_synch);
    pthread_mutex_unlock(&eNB->proc.mutex_synch);

    // if we're not in synch, then run initial synch
    if (eNB->in_synch == 0) { 
      // run intial synch like UE
      LOG_I(PHY,"Running initial synchronization\n");
      
      sync_pos = lte_sync_time_eNB(eNB->common_vars.rxdata[0],
				   fp,
				   fp->samples_per_tti*5,
				   &peak_val,
				   sync_corr);
      LOG_I(PHY,"eNB synch: %d, val %d\n",sync_pos,peak_val);

      if (sync_pos >= 0) {
	if (sync_pos >= fp->nb_prefix_samples)
	  sync_pos2 = sync_pos - fp->nb_prefix_samples;
	else
	  sync_pos2 = sync_pos + (fp->samples_per_tti*10) - fp->nb_prefix_samples;
	
	if (fp->frame_type == FDD) {
	  
	  // PSS is hypothesized in last symbol of first slot in Frame
	  int sync_pos_slot = (fp->samples_per_tti>>1) - fp->ofdm_symbol_size - fp->nb_prefix_samples;
	  
	  if (sync_pos2 >= sync_pos_slot)
	    eNB->rx_offset = sync_pos2 - sync_pos_slot;
	  else
	    eNB->rx_offset = (fp->samples_per_tti*10) + sync_pos2 - sync_pos_slot;
	}
	else {
	  
	}

	LOG_I(PHY,"Estimated sync_pos %d, peak_val %d => timing offset %d\n",sync_pos,peak_val,eNB->rx_offset);
	
1324 1325
	/*
	if ((peak_val > 300000) && (sync_pos > 0)) {
1326 1327 1328 1329
	//      if (sync_pos++ > 3) {
	write_output("eNB_sync.m","sync",(void*)&sync_corr[0],fp->samples_per_tti*5,1,2);
	write_output("eNB_rx.m","rxs",(void*)eNB->common_vars.rxdata[0][0],fp->samples_per_tti*10,1,1);
	exit(-1);
1330 1331 1332
	}
	*/
	eNB->in_synch=1;
1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343
      }
    }

    // release thread
    pthread_mutex_lock(&eNB->proc.mutex_synch);
    eNB->proc.instance_cnt_synch--;
    pthread_mutex_unlock(&eNB->proc.mutex_synch);
  } // oai_exit

  lte_sync_time_free();

Raymond.Knopp's avatar
Raymond.Knopp committed
1344
  return NULL;
1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375
}

int wakeup_synch(PHY_VARS_eNB *eNB){

  struct timespec wait;
  
  wait.tv_sec=0;
  wait.tv_nsec=5000000L;

  // wake up synch thread
  // lock the synch mutex and make sure the thread is ready
  if (pthread_mutex_timedlock(&eNB->proc.mutex_synch,&wait) != 0) {
    LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB synch thread (IC %d)\n", eNB->proc.instance_cnt_synch );
    exit_fun( "error locking mutex_synch" );
    return(-1);
  }
  
  ++eNB->proc.instance_cnt_synch;
  
  // the thread can now be woken up
  if (pthread_cond_signal(&eNB->proc.cond_synch) != 0) {
    LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB synch thread\n");
    exit_fun( "ERROR pthread_cond_signal" );
    return(-1);
  }
  
  pthread_mutex_unlock( &eNB->proc.mutex_synch );

  return(0);
}

1376
/*!
1377 1378 1379
 * \brief The Fronthaul thread of RRU/RAU/RCC/eNB
 * In the case of RRU/eNB, handles interface with external RF
 * In the case of RAU/RCC, handles fronthaul interface with RRU/RAU
1380 1381 1382
 * \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.
 */
Raymond Knopp's avatar
Raymond Knopp committed
1383

1384
static void* eNB_thread_FH( void* param ) {
1385
  
1386
  static int eNB_thread_FH_status;
1387 1388

  eNB_proc_t *proc = (eNB_proc_t*)param;
1389 1390
  PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id];
  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
1391

Sandeep Kumar's avatar
Sandeep Kumar committed
1392
  int subframe=0, frame=0; 
1393

1394
  // set default return value
1395
  eNB_thread_FH_status = 0;
1396

1397
  thread_top_init("eNB_thread_FH",0,870000,1000000,1000000);
1398

Raymond Knopp's avatar
Raymond Knopp committed
1399
  wait_sync("eNB_thread_FH");
1400

1401
#if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME)
Raymond Knopp's avatar
Raymond Knopp committed
1402 1403
  if (eNB->node_function < NGFI_RRU_IF5)
    wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB);
1404
#endif 
1405

1406 1407 1408
  // Start IF device if any
  if (eNB->start_if) 
    if (eNB->start_if(eNB) != 0)
1409
      LOG_E(HW,"Could not start the IF device\n");
1410

Raymond Knopp's avatar
Raymond Knopp committed
1411 1412 1413 1414 1415
  // Start RF device if any
  if (eNB->start_rf)
    if (eNB->start_rf(eNB) != 0)
      LOG_E(HW,"Could not start the RF device\n");

Raymond Knopp's avatar
Raymond Knopp committed
1416
  // wakeup asnych_rxtx thread because the devices are ready at this point
1417 1418 1419 1420 1421
  pthread_mutex_lock(&proc->mutex_asynch_rxtx);
  proc->instance_cnt_asynch_rxtx=0;
  pthread_mutex_unlock(&proc->mutex_asynch_rxtx);
  pthread_cond_signal(&proc->cond_asynch_rxtx);

1422 1423
  // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices
  while (!oai_exit) {
1424

Raymond Knopp's avatar
Raymond Knopp committed
1425 1426
    // these are local subframe/frame counters to check that we are in synch with the fronthaul timing.
    // They are set on the first rx/tx in the underly FH routines.
1427 1428 1429 1430 1431 1432 1433 1434
    if (subframe==9) { 
      subframe=0;
      frame++;
      frame&=1023;
    } else {
      subframe++;
    }      

Raymond Knopp's avatar
Raymond Knopp committed
1435 1436 1437 1438
 
    // synchronization on FH interface, acquire signals/data and block
    if (eNB->rx_fh) eNB->rx_fh(eNB,&frame,&subframe);
    else AssertFatal(1==0, "No fronthaul interface : eNB->node_function %d",eNB->node_function);
1439

Cedric Roux's avatar
Cedric Roux committed
1440 1441
    T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->subframe_rx));

1442 1443
    // At this point, all information for subframe has been received on FH interface
    // If this proc is to provide synchronization, do so
1444
    wakeup_slaves(proc);
1445 1446
      
    // wake up RXn_TXnp4 thread for the subframe
1447
    // choose even or odd thread for RXn-TXnp4 processing 
1448
    if (wakeup_rxtx(proc,&proc->proc_rxtx[proc->subframe_rx&1],fp) < 0)
1449
      break;
1450

Raymond Knopp's avatar
Raymond Knopp committed
1451
    // artifical sleep for very slow fronthaul
1452 1453
    if (eNB->frame_parms.N_RB_DL==6)
      rt_sleep_ns(800000LL);
1454 1455 1456
  }
    
  printf( "Exiting FH thread \n");
Raymond Knopp's avatar
Raymond Knopp committed
1457
 
1458 1459
  eNB_thread_FH_status = 0;
  return &eNB_thread_FH_status;
1460 1461 1462 1463 1464 1465 1466 1467
}


/*!
 * \brief The prach receive thread of eNB.
 * \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.
 */
1468
static void* eNB_thread_prach( void* param ) {
1469 1470 1471 1472
  static int eNB_thread_prach_status;

  eNB_proc_t *proc = (eNB_proc_t*)param;
  PHY_VARS_eNB *eNB= PHY_vars_eNB_g[0][proc->CC_id];
Raymond Knopp's avatar
Raymond Knopp committed
1473

1474 1475 1476
  // set default return value
  eNB_thread_prach_status = 0;

1477
  thread_top_init("eNB_thread_prach",1,500000L,1000000L,20000000L);
1478

1479 1480 1481
  while (!oai_exit) {
    
    if (oai_exit) break;
1482

Raymond Knopp's avatar
Raymond Knopp committed
1483
    if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"eNB_prach_thread") < 0) break;
Raymond Knopp's avatar
Raymond Knopp committed
1484
    
1485
    prach_procedures(eNB);
1486
    
Raymond Knopp's avatar
Raymond Knopp committed
1487
    if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"eNB_prach_thread") < 0) break;
1488 1489 1490 1491 1492 1493
  }

  printf( "Exiting eNB thread PRACH\n");

  eNB_thread_prach_status = 0;
  return &eNB_thread_prach_status;
1494
}
1495

1496 1497


Raymond Knopp's avatar
Raymond Knopp committed
1498
static void* eNB_thread_single( void* param ) {
1499

Raymond Knopp's avatar
Raymond Knopp committed
1500
  static int eNB_thread_single_status;
1501

Raymond Knopp's avatar
Raymond Knopp committed
1502 1503 1504
  eNB_proc_t *proc = (eNB_proc_t*)param;
  eNB_rxtx_proc_t *proc_rxtx = &proc->proc_rxtx[0];
  PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id];
1505
  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
1506
  eNB->CC_id =  proc->CC_id;
1507 1508

  void *rxp[2],*rxp2[2];
1509

Raymond Knopp's avatar
Raymond Knopp committed
1510
  int subframe=0, frame=0; 
1511

1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523
  int32_t dummy_rx[fp->nb_antennas_rx][fp->samples_per_tti] __attribute__((aligned(32)));

  int ic;

  int rxs;

  int i;

  // initialize the synchronization buffer to the common_vars.rxdata
  for (int i=0;i<fp->nb_antennas_rx;i++)
    rxp[i] = &eNB->common_vars.rxdata[0][i][0];

Raymond Knopp's avatar
Raymond Knopp committed
1524 1525
  // set default return value
  eNB_thread_single_status = 0;
1526

1527
  thread_top_init("eNB_thread_single",0,870000,1000000,1000000);
1528

Raymond Knopp's avatar
Raymond Knopp committed
1529
  wait_sync("eNB_thread_single");
1530

1531
#if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME)
Raymond Knopp's avatar
Raymond Knopp committed
1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550
  if (eNB->node_function < NGFI_RRU_IF5)
    wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB);
#endif 

  // Start IF device if any
  if (eNB->start_if) 
    if (eNB->start_if(eNB) != 0)
      LOG_E(HW,"Could not start the IF device\n");

  // Start RF device if any
  if (eNB->start_rf)
    if (eNB->start_rf(eNB) != 0)
      LOG_E(HW,"Could not start the RF device\n");

  // wakeup asnych_rxtx thread because the devices are ready at this point
  pthread_mutex_lock(&proc->mutex_asynch_rxtx);
  proc->instance_cnt_asynch_rxtx=0;
  pthread_mutex_unlock(&proc->mutex_asynch_rxtx);
  pthread_cond_signal(&proc->cond_asynch_rxtx);
1551

1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573


  // if this is a slave eNB, try to synchronize on the DL frequency
  if ((eNB->is_slave) &&
      ((eNB->node_function >= NGFI_RRU_IF5))) {
    // if FDD, switch RX on DL frequency
    
    double temp_freq1 = eNB->rfdevice.openair0_cfg->rx_freq[0];
    double temp_freq2 = eNB->rfdevice.openair0_cfg->tx_freq[0];
    for (i=0;i<4;i++) {
      eNB->rfdevice.openair0_cfg->rx_freq[i] = eNB->rfdevice.openair0_cfg->tx_freq[i];
      eNB->rfdevice.openair0_cfg->tx_freq[i] = temp_freq1;
    }
    eNB->rfdevice.trx_set_freq_func(&eNB->rfdevice,eNB->rfdevice.openair0_cfg,0);

    while ((eNB->in_synch ==0)&&(!oai_exit)) {
      // read in frame
      rxs = eNB->rfdevice.trx_read_func(&eNB->rfdevice,
					&(proc->timestamp_rx),
					rxp,
					fp->samples_per_tti*10,
					fp->nb_antennas_rx);
Raymond.Knopp's avatar
Raymond.Knopp committed
1574 1575 1576 1577

      if (rxs != (fp->samples_per_tti*10))
	exit_fun("Problem receiving samples\n");

1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593
      // wakeup synchronization processing thread
      wakeup_synch(eNB);
      ic=0;
      
      while ((ic>=0)&&(!oai_exit)) {
	// continuously read in frames, 1ms at a time, 
	// until we are done with the synchronization procedure
	
	for (i=0; i<fp->nb_antennas_rx; i++)
	  rxp2[i] = (void*)&dummy_rx[i][0];
	for (i=0;i<10;i++)
	  rxs = eNB->rfdevice.trx_read_func(&eNB->rfdevice,
					    &(proc->timestamp_rx),
					    rxp2,
					    fp->samples_per_tti,
					    fp->nb_antennas_rx);
Raymond.Knopp's avatar
Raymond.Knopp committed
1594 1595 1596
	if (rxs != fp->samples_per_tti)
	  exit_fun( "problem receiving samples" );

1597 1598 1599 1600 1601
	pthread_mutex_lock(&eNB->proc.mutex_synch);
	ic = eNB->proc.instance_cnt_synch;
	pthread_mutex_unlock(&eNB->proc.mutex_synch);
      } // ic>=0
    } // in_synch==0
1602 1603 1604 1605 1606 1607 1608
    // read in rx_offset samples
    LOG_I(PHY,"Resynchronizing by %d samples\n",eNB->rx_offset);
    rxs = eNB->rfdevice.trx_read_func(&eNB->rfdevice,
				      &(proc->timestamp_rx),
				      rxp,
				      eNB->rx_offset,
				      fp->nb_antennas_rx);
Raymond.Knopp's avatar
Raymond.Knopp committed
1609 1610 1611
    if (rxs != eNB->rx_offset)
      exit_fun( "problem receiving samples" );

1612 1613
    for (i=0;i<4;i++) {
      eNB->rfdevice.openair0_cfg->rx_freq[i] = temp_freq1;
1614
      eNB->rfdevice.openair0_cfg->tx_freq[i] = temp_freq2;
1615
    }
1616
    eNB->rfdevice.trx_set_freq_func(&eNB->rfdevice,eNB->rfdevice.openair0_cfg,1);
1617 1618 1619
  } // if RRU and slave


Raymond Knopp's avatar
Raymond Knopp committed
1620
  // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices
1621 1622
  while (!oai_exit) {

Raymond Knopp's avatar
Raymond Knopp committed
1623 1624 1625 1626 1627 1628 1629 1630 1631
    // these are local subframe/frame counters to check that we are in synch with the fronthaul timing.
    // They are set on the first rx/tx in the underly FH routines.
    if (subframe==9) { 
      subframe=0;
      frame++;
      frame&=1023;
    } else {
      subframe++;
    }      
1632

Raymond.Knopp's avatar
Raymond.Knopp committed
1633
    if (eNB->CC_id==1) 
1634
	LOG_D(PHY,"eNB thread single %p (proc %p, CC_id %d), frame %d (%p), subframe %d (%p)\n",
luhan wang's avatar
luhan wang committed
1635
	  pthread_self(), proc, eNB->CC_id, frame,&frame,subframe,&subframe);
Raymond Knopp's avatar
Raymond Knopp committed
1636 1637 1638 1639 1640 1641 1642
 
    // synchronization on FH interface, acquire signals/data and block
    if (eNB->rx_fh) eNB->rx_fh(eNB,&frame,&subframe);
    else AssertFatal(1==0, "No fronthaul interface : eNB->node_function %d",eNB->node_function);

    T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->subframe_rx));

1643 1644 1645
    proc_rxtx->subframe_rx = proc->subframe_rx;
    proc_rxtx->frame_rx    = proc->frame_rx;
    proc_rxtx->subframe_tx = (proc->subframe_rx+4)%10;
1646 1647
    proc_rxtx->frame_tx    = (proc->subframe_rx>5) ? (1+proc->frame_rx)&1023 : proc->frame_rx;
    proc->frame_tx         = proc_rxtx->frame_tx;
1648
    proc_rxtx->timestamp_tx = proc->timestamp_tx;
1649 1650
    // adjust for timing offset between RRU
    if (eNB->CC_id!=0) proc_rxtx->frame_tx = (proc_rxtx->frame_tx+proc->frame_offset)&1023;
1651

Raymond Knopp's avatar
Raymond Knopp committed
1652 1653 1654 1655 1656
    // At this point, all information for subframe has been received on FH interface
    // If this proc is to provide synchronization, do so
    wakeup_slaves(proc);

    if (rxtx(eNB,proc_rxtx,"eNB_thread_single") < 0) break;
1657
  }
Raymond Knopp's avatar
Raymond Knopp committed
1658
  
1659

Raymond Knopp's avatar
Raymond Knopp committed
1660 1661 1662 1663
  printf( "Exiting eNB_single thread \n");
 
  eNB_thread_single_status = 0;
  return &eNB_thread_single_status;
Raymond Knopp's avatar
Raymond Knopp committed
1664

1665 1666
}

1667
extern void init_fep_thread(PHY_VARS_eNB *, pthread_attr_t *);
1668 1669
extern void init_td_thread(PHY_VARS_eNB *, pthread_attr_t *);
extern void init_te_thread(PHY_VARS_eNB *, pthread_attr_t *);
1670

1671
void init_eNB_proc(int inst) {
1672
  
Rohit Gupta's avatar
Rohit Gupta committed
1673
  int i=0;
1674
  int CC_id;
1675 1676
  PHY_VARS_eNB *eNB;
  eNB_proc_t *proc;
1677
  eNB_rxtx_proc_t *proc_rxtx;
1678
  pthread_attr_t *attr0=NULL,*attr1=NULL,*attr_FH=NULL,*attr_prach=NULL,*attr_asynch=NULL,*attr_single=NULL,*attr_fep=NULL,*attr_td=NULL,*attr_te=NULL,*attr_synch=NULL;
Raymond Knopp's avatar
Raymond Knopp committed
1679

1680 1681
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    eNB = PHY_vars_eNB_g[inst][CC_id];
laurent's avatar
laurent committed
1682
#ifndef OCP_FRAMEWORK
1683
    LOG_I(PHY,"Initializing eNB %d CC_id %d (%s,%s),\n",inst,CC_id,eNB_functions[eNB->node_function],eNB_timing[eNB->node_timing]);
laurent's avatar
laurent committed
1684
#endif
1685
    proc = &eNB->proc;
Raymond Knopp's avatar
Raymond Knopp committed
1686

1687 1688 1689
    proc_rxtx = proc->proc_rxtx;
    proc_rxtx[0].instance_cnt_rxtx = -1;
    proc_rxtx[1].instance_cnt_rxtx = -1;
1690 1691
    proc->instance_cnt_prach       = -1;
    proc->instance_cnt_FH          = -1;
1692
    proc->instance_cnt_asynch_rxtx = -1;
1693
    proc->CC_id = CC_id;    
1694 1695
    proc->instance_cnt_synch        =  -1;

Raymond Knopp's avatar
Raymond Knopp committed
1696 1697
    proc->first_rx=1;
    proc->first_tx=1;
1698
    proc->frame_offset = 0;
Raymond Knopp's avatar
Raymond Knopp committed
1699

1700
    for (i=0;i<10;i++) proc->symbol_mask[i]=0;
Raymond Knopp's avatar
Raymond Knopp committed
1701

1702 1703 1704 1705
    pthread_mutex_init( &proc_rxtx[0].mutex_rxtx, NULL);
    pthread_mutex_init( &proc_rxtx[1].mutex_rxtx, NULL);
    pthread_cond_init( &proc_rxtx[0].cond_rxtx, NULL);
    pthread_cond_init( &proc_rxtx[1].cond_rxtx, NULL);
Raymond Knopp's avatar
Raymond Knopp committed
1706 1707 1708

    pthread_mutex_init( &proc->mutex_prach, NULL);
    pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL);
1709
    pthread_mutex_init( &proc->mutex_synch,NULL);
Raymond Knopp's avatar
Raymond Knopp committed
1710

1711 1712
    pthread_cond_init( &proc->cond_prach, NULL);
    pthread_cond_init( &proc->cond_FH, NULL);
1713
    pthread_cond_init( &proc->cond_asynch_rxtx, NULL);
1714
    pthread_cond_init( &proc->cond_synch,NULL);
1715 1716 1717

    pthread_attr_init( &proc->attr_FH);
    pthread_attr_init( &proc->attr_prach);
1718
    pthread_attr_init( &proc->attr_synch);
1719 1720 1721
    pthread_attr_init( &proc->attr_asynch_rxtx);
    pthread_attr_init( &proc->attr_single);
    pthread_attr_init( &proc->attr_fep);
1722 1723
    pthread_attr_init( &proc->attr_td);
    pthread_attr_init( &proc->attr_te);
1724 1725
    pthread_attr_init( &proc_rxtx[0].attr_rxtx);
    pthread_attr_init( &proc_rxtx[1].attr_rxtx);
1726
#ifndef DEADLINE_SCHEDULER
Raymond Knopp's avatar
Raymond Knopp committed
1727 1728 1729 1730
    attr0       = &proc_rxtx[0].attr_rxtx;
    attr1       = &proc_rxtx[1].attr_rxtx;
    attr_FH     = &proc->attr_FH;
    attr_prach  = &proc->attr_prach;
1731
    attr_synch  = &proc->attr_synch;
Raymond Knopp's avatar
Raymond Knopp committed
1732 1733
    attr_asynch = &proc->attr_asynch_rxtx;
    attr_single = &proc->attr_single;
1734
    attr_fep    = &proc->attr_fep;
1735 1736
    attr_td     = &proc->attr_td;
    attr_te     = &proc->attr_te; 
Raymond Knopp's avatar
Raymond Knopp committed
1737 1738 1739 1740 1741 1742 1743
#endif

    if (eNB->single_thread_flag==0) {
      pthread_create( &proc_rxtx[0].pthread_rxtx, attr0, eNB_thread_rxtx, &proc_rxtx[0] );
      pthread_create( &proc_rxtx[1].pthread_rxtx, attr1, eNB_thread_rxtx, &proc_rxtx[1] );
      pthread_create( &proc->pthread_FH, attr_FH, eNB_thread_FH, &eNB->proc );
    }
1744
    else {
Raymond Knopp's avatar
Raymond Knopp committed
1745
      pthread_create(&proc->pthread_single, attr_single, eNB_thread_single, &eNB->proc);
1746
      init_fep_thread(eNB,attr_fep);
1747 1748
      init_td_thread(eNB,attr_td);
      init_te_thread(eNB,attr_te);
1749
    }
Raymond Knopp's avatar
Raymond Knopp committed
1750
    pthread_create( &proc->pthread_prach, attr_prach, eNB_thread_prach, &eNB->proc );
1751
    pthread_create( &proc->pthread_synch, attr_synch, eNB_thread_synch, eNB);
1752
    if ((eNB->node_timing == synch_to_other) ||
Raymond Knopp's avatar
Raymond Knopp committed
1753 1754
	(eNB->node_function == NGFI_RRU_IF5) ||
	(eNB->node_function == NGFI_RRU_IF4p5))
1755 1756


Raymond Knopp's avatar
Raymond Knopp committed
1757 1758
      pthread_create( &proc->pthread_asynch_rxtx, attr_asynch, eNB_thread_asynch_rxtx, &eNB->proc );

1759
    char name[16];
1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771
    if (eNB->single_thread_flag == 0) {
      snprintf( name, sizeof(name), "RXTX0 %d", i );
      pthread_setname_np( proc_rxtx[0].pthread_rxtx, name );
      snprintf( name, sizeof(name), "RXTX1 %d", i );
      pthread_setname_np( proc_rxtx[1].pthread_rxtx, name );
      snprintf( name, sizeof(name), "FH %d", i );
      pthread_setname_np( proc->pthread_FH, name );
    }
    else {
      snprintf( name, sizeof(name), " %d", i );
      pthread_setname_np( proc->pthread_single, name );
    }
1772
  }
1773

1774
  //for multiple CCs: setup master and slaves
1775
 /* 
1776
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1777 1778
    eNB = PHY_vars_eNB_g[inst][CC_id];

1779
    if (eNB->node_timing == synch_to_ext_device) { //master
1780 1781 1782 1783
      eNB->proc.num_slaves = MAX_NUM_CCs-1;
      eNB->proc.slave_proc = (eNB_proc_t**)malloc(eNB->proc.num_slaves*sizeof(eNB_proc_t*));

      for (i=0; i< eNB->proc.num_slaves; i++) {
1784 1785
        if (i < CC_id)  eNB->proc.slave_proc[i] = &(PHY_vars_eNB_g[inst][i]->proc);
        if (i >= CC_id)  eNB->proc.slave_proc[i] = &(PHY_vars_eNB_g[inst][i+1]->proc);
1786 1787
      }
    }
1788 1789
    }
*/
1790

1791 1792 1793 1794
  /* setup PHY proc TX sync mechanism */
  pthread_mutex_init(&sync_phy_proc.mutex_phy_proc_tx, NULL);
  pthread_cond_init(&sync_phy_proc.cond_phy_proc_tx, NULL);
  sync_phy_proc.phy_proc_CC_id = 0;
1795 1796
}

1797

1798

1799 1800 1801
/*!
 * \brief Terminate eNB TX and RX threads.
 */
1802
void kill_eNB_proc(int inst) {
1803

1804
  int *status;
1805 1806
  PHY_VARS_eNB *eNB;
  eNB_proc_t *proc;
1807
  eNB_rxtx_proc_t *proc_rxtx;
1808
  for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1809
    eNB=PHY_vars_eNB_g[inst][CC_id];
1810 1811
    
    proc = &eNB->proc;
1812
    proc_rxtx = &proc->proc_rxtx[0];
1813
    
1814
#ifdef DEBUG_THREADS
1815
    printf( "Killing TX CC_id %d thread %d\n", CC_id, i );
1816
#endif
1817
    
1818 1819
    proc_rxtx[0].instance_cnt_rxtx = 0; // FIXME data race!
    proc_rxtx[1].instance_cnt_rxtx = 0; // FIXME data race!
Raymond Knopp's avatar
Raymond Knopp committed
1820
    proc->instance_cnt_prach = 0;
1821
    proc->instance_cnt_FH = 0;
1822
    pthread_cond_signal( &proc_rxtx[0].cond_rxtx );    
Raymond Knopp's avatar
Raymond Knopp committed
1823 1824
    pthread_cond_signal( &proc_rxtx[1].cond_rxtx );
    pthread_cond_signal( &proc->cond_prach );
1825
    pthread_cond_signal( &proc->cond_FH );
1826
    pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx);
Raymond Knopp's avatar
Raymond Knopp committed
1827

1828 1829 1830 1831 1832 1833 1834
    pthread_join( proc->pthread_FH, (void**)&status ); 
    pthread_mutex_destroy( &proc->mutex_FH );
    pthread_cond_destroy( &proc->cond_FH );
            
    pthread_join( proc->pthread_prach, (void**)&status );    
    pthread_mutex_destroy( &proc->mutex_prach );
    pthread_cond_destroy( &proc->cond_prach );         
1835

1836
    int i;
Raymond Knopp's avatar
Raymond Knopp committed
1837
    for (i=0;i<2;i++) {
1838 1839 1840 1841
      pthread_join( proc_rxtx[i].pthread_rxtx, (void**)&status );
      pthread_mutex_destroy( &proc_rxtx[i].mutex_rxtx );
      pthread_cond_destroy( &proc_rxtx[i].cond_rxtx );
    }
1842
  }
1843 1844
}

1845

1846 1847 1848 1849
/* this function maps the phy_vars_eNB tx and rx buffers to the available rf chains.
   Each rf chain is is addressed by the card number and the chain on the card. The
   rf_map specifies for each CC, on which rf chain the mapping should start. Multiple
   antennas are mapped to successive RF chains on the same card. */
1850
int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg) {
1851

1852 1853
  int i,j; 
  int CC_id,card,ant;
1854

1855
  //uint16_t N_TA_offset = 0;
1856

1857 1858 1859 1860
  LTE_DL_FRAME_PARMS *frame_parms;

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    if (phy_vars_eNB[CC_id]) {
1861
      frame_parms = &(phy_vars_eNB[CC_id]->frame_parms);
1862 1863 1864 1865 1866 1867
      printf("setup_eNB_buffers: frame_parms = %p\n",frame_parms);
    } else {
      printf("phy_vars_eNB[%d] not initialized\n", CC_id);
      return(-1);
    }

1868
    /*
1869 1870 1871 1872 1873 1874 1875 1876
    if (frame_parms->frame_type == TDD) {
      if (frame_parms->N_RB_DL == 100)
        N_TA_offset = 624;
      else if (frame_parms->N_RB_DL == 50)
        N_TA_offset = 624/2;
      else if (frame_parms->N_RB_DL == 25)
        N_TA_offset = 624/4;
    }
1877
    */
Raymond Knopp's avatar
Raymond Knopp committed
1878
 
1879

Raymond Knopp's avatar
Raymond Knopp committed
1880
    if (openair0_cfg[CC_id].mmapped_dma == 1) {
1881
    // replace RX signal buffers with mmaped HW versions
Raymond Knopp's avatar
Raymond Knopp committed
1882 1883
      
      for (i=0; i<frame_parms->nb_antennas_rx; i++) {
1884 1885 1886
	card = i/4;
	ant = i%4;
	printf("Mapping eNB CC_id %d, rx_ant %d, on card %d, chain %d\n",CC_id,i,phy_vars_eNB[CC_id]->rf_map.card+card, phy_vars_eNB[CC_id]->rf_map.chain+ant);
Raymond Knopp's avatar
Raymond Knopp committed
1887
	free(phy_vars_eNB[CC_id]->common_vars.rxdata[0][i]);
1888
	phy_vars_eNB[CC_id]->common_vars.rxdata[0][i] = openair0_cfg[phy_vars_eNB[CC_id]->rf_map.card+card].rxbase[phy_vars_eNB[CC_id]->rf_map.chain+ant];
Raymond Knopp's avatar
Raymond Knopp committed
1889 1890 1891 1892 1893 1894
	
	printf("rxdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->common_vars.rxdata[0][i]);
	for (j=0; j<16; j++) {
	  printf("rxbuffer %d: %x\n",j,phy_vars_eNB[CC_id]->common_vars.rxdata[0][i][j]);
	  phy_vars_eNB[CC_id]->common_vars.rxdata[0][i][j] = 16-j;
	}
1895
      }
Raymond Knopp's avatar
Raymond Knopp committed
1896 1897
      
      for (i=0; i<frame_parms->nb_antennas_tx; i++) {
1898 1899 1900
	card = i/4;
	ant = i%4;
	printf("Mapping eNB CC_id %d, tx_ant %d, on card %d, chain %d\n",CC_id,i,phy_vars_eNB[CC_id]->rf_map.card+card, phy_vars_eNB[CC_id]->rf_map.chain+ant);
Raymond Knopp's avatar
Raymond Knopp committed
1901
	free(phy_vars_eNB[CC_id]->common_vars.txdata[0][i]);
1902
	phy_vars_eNB[CC_id]->common_vars.txdata[0][i] = openair0_cfg[phy_vars_eNB[CC_id]->rf_map.card+card].txbase[phy_vars_eNB[CC_id]->rf_map.chain+ant];
Raymond Knopp's avatar
Raymond Knopp committed
1903 1904 1905 1906 1907 1908 1909
	
	printf("txdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->common_vars.txdata[0][i]);
	
	for (j=0; j<16; j++) {
	  printf("txbuffer %d: %x\n",j,phy_vars_eNB[CC_id]->common_vars.txdata[0][i][j]);
	  phy_vars_eNB[CC_id]->common_vars.txdata[0][i][j] = 16-j;
	}
1910 1911
      }
    }
Raymond Knopp's avatar
Raymond Knopp committed
1912
    else {  // not memory-mapped DMA 
1913 1914
      //nothing to do, everything already allocated in lte_init
      /*
Raymond Knopp's avatar
Raymond Knopp committed
1915 1916 1917 1918 1919
      rxdata = (int32_t**)malloc16(frame_parms->nb_antennas_rx*sizeof(int32_t*));
      txdata = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*));
      
      for (i=0; i<frame_parms->nb_antennas_rx; i++) {
	free(phy_vars_eNB[CC_id]->common_vars.rxdata[0][i]);
1920
	rxdata[i] = (int32_t*)(32 + malloc16(32+frame_parms->samples_per_tti*10*sizeof(int32_t))); // FIXME broken memory allocation
1921
	phy_vars_eNB[CC_id]->common_vars.rxdata[0][i] = rxdata[i]; //-N_TA_offset; // N_TA offset for TDD         FIXME! N_TA_offset > 16 => access of unallocated memory
1922
	memset(rxdata[i], 0, frame_parms->samples_per_tti*10*sizeof(int32_t));
Raymond Knopp's avatar
Raymond Knopp committed
1923
	printf("rxdata[%d] @ %p (%p) (N_TA_OFFSET %d)\n", i, phy_vars_eNB[CC_id]->common_vars.rxdata[0][i],rxdata[i],N_TA_offset);      
1924 1925
      }
      
Raymond Knopp's avatar
Raymond Knopp committed
1926 1927
      for (i=0; i<frame_parms->nb_antennas_tx; i++) {
	free(phy_vars_eNB[CC_id]->common_vars.txdata[0][i]);
1928
	txdata[i] = (int32_t*)(32 + malloc16(32 + frame_parms->samples_per_tti*10*sizeof(int32_t))); // FIXME broken memory allocation
Raymond Knopp's avatar
Raymond Knopp committed
1929
	phy_vars_eNB[CC_id]->common_vars.txdata[0][i] = txdata[i];
1930
	memset(txdata[i],0, frame_parms->samples_per_tti*10*sizeof(int32_t));
Raymond Knopp's avatar
Raymond Knopp committed
1931
	printf("txdata[%d] @ %p\n", i, phy_vars_eNB[CC_id]->common_vars.txdata[0][i]);
1932
      }
1933
      */
1934 1935 1936 1937 1938 1939 1940 1941
    }
  }

  return(0);
}


void reset_opp_meas(void) {
1942

1943 1944 1945 1946 1947
  int sfn;
  reset_meas(&softmodem_stats_mt);
  reset_meas(&softmodem_stats_hw);
  
  for (sfn=0; sfn < 10; sfn++) {
1948
    reset_meas(&softmodem_stats_rxtx_sf);
1949
    reset_meas(&softmodem_stats_rx_sf);
1950 1951 1952
  }
}

1953

1954 1955 1956 1957 1958 1959 1960
void print_opp_meas(void) {

  int sfn=0;
  print_meas(&softmodem_stats_mt, "Main ENB Thread", NULL, NULL);
  print_meas(&softmodem_stats_hw, "HW Acquisation", NULL, NULL);
  
  for (sfn=0; sfn < 10; sfn++) {
1961
    print_meas(&softmodem_stats_rxtx_sf,"[eNB][total_phy_proc_rxtx]",NULL, NULL);
1962
    print_meas(&softmodem_stats_rx_sf,"[eNB][total_phy_proc_rx]",NULL,NULL);
1963 1964
  }
}
1965
 
1966 1967 1968 1969 1970 1971 1972
int start_if(PHY_VARS_eNB *eNB) {
  return(eNB->ifdevice.trx_start_func(&eNB->ifdevice));
}

int start_rf(PHY_VARS_eNB *eNB) {
  return(eNB->rfdevice.trx_start_func(&eNB->rfdevice));
}
1973

Raymond.Knopp's avatar
Raymond.Knopp committed
1974
extern void eNB_fep_rru_if5(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc);
1975 1976
extern void eNB_fep_full(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc);
extern void eNB_fep_full_2thread(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc);
1977
extern void do_prach(PHY_VARS_eNB *eNB,int frame,int subframe);
1978

1979
void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst,eth_params_t *eth_params,int single_thread_flag,int wait_for_sync) {
1980
  
1981
  int CC_id;
1982
  int inst;
1983
  PHY_VARS_eNB *eNB;
Raymond Knopp's avatar
Raymond Knopp committed
1984 1985
  int ret;

1986 1987
  for (inst=0;inst<nb_inst;inst++) {
    for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
1988 1989 1990
      eNB = PHY_vars_eNB_g[inst][CC_id]; 
      eNB->node_function      = node_function[CC_id];
      eNB->node_timing        = node_timing[CC_id];
1991
      eNB->eth_params         = eth_params+CC_id;
1992
      eNB->abstraction_flag   = 0;
Raymond Knopp's avatar
Raymond Knopp committed
1993
      eNB->single_thread_flag = single_thread_flag;
Raymond Knopp's avatar
Raymond Knopp committed
1994
      eNB->ts_offset          = 0;
1995 1996 1997
      eNB->in_synch           = 0;
      eNB->is_slave           = (wait_for_sync>0) ? 1 : 0;

1998

laurent's avatar
laurent committed
1999
#ifndef OCP_FRAMEWORK
2000
      LOG_I(PHY,"Initializing eNB %d CC_id %d : (%s,%s)\n",inst,CC_id,eNB_functions[node_function[CC_id]],eNB_timing[node_timing[CC_id]]);
laurent's avatar
laurent committed
2001
#endif
Raymond Knopp's avatar
Raymond Knopp committed
2002

2003 2004
      switch (node_function[CC_id]) {
      case NGFI_RRU_IF5:
Raymond Knopp's avatar
Raymond Knopp committed
2005
	eNB->do_prach             = NULL;
2006
	eNB->do_precoding         = 0;
Raymond Knopp's avatar
Raymond Knopp committed
2007
	eNB->fep                  = eNB_fep_rru_if5;
2008 2009
	eNB->td                   = NULL;
	eNB->te                   = NULL;
Raymond Knopp's avatar
Raymond Knopp committed
2010
	eNB->proc_uespec_rx       = NULL;
2011
	eNB->proc_tx              = NULL;
Raymond Knopp's avatar
Raymond Knopp committed
2012 2013 2014 2015
	eNB->tx_fh                = NULL;
	eNB->rx_fh                = rx_rf;
	eNB->start_rf             = start_rf;
	eNB->start_if             = start_if;
Raymond Knopp's avatar
Raymond Knopp committed
2016
	eNB->fh_asynch            = fh_if5_asynch_DL;
2017 2018 2019 2020 2021 2022 2023
	if (oaisim_flag == 0) {
	  ret = openair0_device_load(&eNB->rfdevice, &openair0_cfg[CC_id]);
	  if (ret<0) {
	    printf("Exiting, cannot initialize rf device\n");
	    exit(-1);
	  }
	}
Raymond Knopp's avatar
Raymond Knopp committed
2024 2025
	eNB->rfdevice.host_type   = RRH_HOST;
	eNB->ifdevice.host_type   = RRH_HOST;
2026
        ret = openair0_transport_load(&eNB->ifdevice, &openair0_cfg[CC_id], eNB->eth_params);
Raymond Knopp's avatar
Raymond Knopp committed
2027 2028 2029 2030 2031
	printf("openair0_transport_init returns %d for CC_id %d\n",ret,CC_id);
        if (ret<0) {
          printf("Exiting, cannot initialize transport protocol\n");
          exit(-1);
        }
2032 2033
	break;
      case NGFI_RRU_IF4p5:
2034
	eNB->do_precoding         = 0;
Raymond Knopp's avatar
Raymond Knopp committed
2035
	eNB->do_prach             = do_prach;
hutch's avatar
hutch committed
2036
	eNB->fep                  = eNB_fep_full;//(single_thread_flag==1) ? eNB_fep_full_2thread : eNB_fep_full;
2037 2038
	eNB->td                   = NULL;
	eNB->te                   = NULL;
Raymond Knopp's avatar
Raymond Knopp committed
2039
	eNB->proc_uespec_rx       = NULL;
Raymond Knopp's avatar
Raymond Knopp committed
2040
	eNB->proc_tx              = NULL;//proc_tx_rru_if4p5;
Raymond Knopp's avatar
Raymond Knopp committed
2041 2042
	eNB->tx_fh                = NULL;
	eNB->rx_fh                = rx_rf;
Raymond Knopp's avatar
Raymond Knopp committed
2043
	eNB->fh_asynch            = fh_if4p5_asynch_DL;
Raymond Knopp's avatar
Raymond Knopp committed
2044 2045
	eNB->start_rf             = start_rf;
	eNB->start_if             = start_if;
2046 2047 2048 2049 2050 2051 2052
	if (oaisim_flag == 0) {
	  ret = openair0_device_load(&eNB->rfdevice, &openair0_cfg[CC_id]);
	  if (ret<0) {
	    printf("Exiting, cannot initialize rf device\n");
	    exit(-1);
	  }
	}
Raymond Knopp's avatar
Raymond Knopp committed
2053 2054
	eNB->rfdevice.host_type   = RRH_HOST;
	eNB->ifdevice.host_type   = RRH_HOST;
2055
	printf("loading transport interface ...\n");
2056
        ret = openair0_transport_load(&eNB->ifdevice, &openair0_cfg[CC_id], eNB->eth_params);
Raymond Knopp's avatar
Raymond Knopp committed
2057 2058 2059 2060 2061 2062
	printf("openair0_transport_init returns %d for CC_id %d\n",ret,CC_id);
        if (ret<0) {
          printf("Exiting, cannot initialize transport protocol\n");
          exit(-1);
        }

2063
	malloc_IF4p5_buffer(eNB);
Raymond Knopp's avatar
Raymond Knopp committed
2064

2065 2066
	break;
      case eNodeB_3GPP:
Florian Kaltenberger's avatar
Florian Kaltenberger committed
2067
	eNB->do_precoding         = eNB->frame_parms.nb_antennas_tx!=eNB->frame_parms.nb_antenna_ports_eNB;
Raymond Knopp's avatar
Raymond Knopp committed
2068
	eNB->do_prach             = do_prach;
hutch's avatar
hutch committed
2069
	eNB->fep                  = eNB_fep_full;//(single_thread_flag==1) ? eNB_fep_full_2thread : eNB_fep_full;
2070 2071
	eNB->td                   = ulsch_decoding_data;//(single_thread_flag==1) ? ulsch_decoding_data_2thread : ulsch_decoding_data;
	eNB->te                   = dlsch_encoding;//(single_thread_flag==1) ? dlsch_encoding_2threads : dlsch_encoding;
Raymond Knopp's avatar
Raymond Knopp committed
2072 2073 2074 2075 2076 2077
	eNB->proc_uespec_rx       = phy_procedures_eNB_uespec_RX;
	eNB->proc_tx              = proc_tx_full;
	eNB->tx_fh                = NULL;
	eNB->rx_fh                = rx_rf;
	eNB->start_rf             = start_rf;
	eNB->start_if             = NULL;
Raymond Knopp's avatar
Raymond Knopp committed
2078
        eNB->fh_asynch            = NULL;
2079 2080 2081 2082 2083 2084
        if (oaisim_flag == 0) {
  	  ret = openair0_device_load(&eNB->rfdevice, &openair0_cfg[CC_id]);
          if (ret<0) {
            printf("Exiting, cannot initialize rf device\n");
            exit(-1);
          }
Raymond Knopp's avatar
Raymond Knopp committed
2085 2086 2087
        }
	eNB->rfdevice.host_type   = BBU_HOST;
	eNB->ifdevice.host_type   = BBU_HOST;
2088 2089
	break;
      case eNodeB_3GPP_BBU:
2090
	eNB->do_precoding         = eNB->frame_parms.nb_antennas_tx!=eNB->frame_parms.nb_antenna_ports_eNB;
2091 2092 2093 2094 2095 2096
	eNB->do_prach             = do_prach;
	eNB->fep                  = eNB_fep_full;//(single_thread_flag==1) ? eNB_fep_full_2thread : eNB_fep_full;
	eNB->td                   = ulsch_decoding_data;//(single_thread_flag==1) ? ulsch_decoding_data_2thread : ulsch_decoding_data;
	eNB->te                   = dlsch_encoding;//(single_thread_flag==1) ? dlsch_encoding_2threads : dlsch_encoding;
	eNB->proc_uespec_rx       = phy_procedures_eNB_uespec_RX;
	eNB->proc_tx              = proc_tx_full;
2097
        if (eNB->node_timing == synch_to_other) {
2098 2099 2100
           eNB->tx_fh             = tx_fh_if5_mobipass;
           eNB->rx_fh             = rx_fh_slave;
           eNB->fh_asynch         = fh_if5_asynch_UL;
2101 2102 2103

        }
        else {
2104 2105 2106
           eNB->tx_fh             = tx_fh_if5;
           eNB->rx_fh             = rx_fh_if5;
           eNB->fh_asynch         = NULL;
2107
        }
Raymond Knopp's avatar
Raymond Knopp committed
2108

2109 2110
	eNB->start_rf             = NULL;
	eNB->start_if             = start_if;
Raymond Knopp's avatar
Raymond Knopp committed
2111 2112 2113
	eNB->rfdevice.host_type   = BBU_HOST;

	eNB->ifdevice.host_type   = BBU_HOST;
Raymond Knopp's avatar
Raymond Knopp committed
2114

2115
        ret = openair0_transport_load(&eNB->ifdevice, &openair0_cfg[CC_id], eNB->eth_params);
Raymond Knopp's avatar
Raymond Knopp committed
2116 2117 2118 2119 2120
        printf("openair0_transport_init returns %d for CC_id %d\n",ret,CC_id);
        if (ret<0) {
          printf("Exiting, cannot initialize transport protocol\n");
          exit(-1);
        }
2121 2122
	break;
      case NGFI_RCC_IF4p5:
2123
	eNB->do_precoding         = 0;
Raymond Knopp's avatar
Raymond Knopp committed
2124 2125
	eNB->do_prach             = do_prach;
	eNB->fep                  = NULL;
hutch's avatar
hutch committed
2126 2127
	eNB->td                   = ulsch_decoding_data;//(single_thread_flag==1) ? ulsch_decoding_data_2thread : ulsch_decoding_data;
	eNB->te                   = dlsch_encoding;//(single_thread_flag==1) ? dlsch_encoding_2threads : dlsch_encoding;
Raymond Knopp's avatar
Raymond Knopp committed
2128 2129 2130 2131 2132 2133 2134
	eNB->proc_uespec_rx       = phy_procedures_eNB_uespec_RX;
	eNB->proc_tx              = proc_tx_high;
	eNB->tx_fh                = tx_fh_if4p5;
	eNB->rx_fh                = rx_fh_if4p5;
	eNB->start_rf             = NULL;
	eNB->start_if             = start_if;
        eNB->fh_asynch            = (eNB->node_timing == synch_to_other) ? fh_if4p5_asynch_UL : NULL;
Raymond Knopp's avatar
Raymond Knopp committed
2135 2136
	eNB->rfdevice.host_type   = BBU_HOST;
	eNB->ifdevice.host_type   = BBU_HOST;
2137
        ret = openair0_transport_load(&eNB->ifdevice, &openair0_cfg[CC_id], eNB->eth_params);
Raymond Knopp's avatar
Raymond Knopp committed
2138 2139 2140 2141 2142
        printf("openair0_transport_init returns %d for CC_id %d\n",ret,CC_id);
        if (ret<0) {
          printf("Exiting, cannot initialize transport protocol\n");
          exit(-1);
        }
2143
	malloc_IF4p5_buffer(eNB);
Raymond Knopp's avatar
Raymond Knopp committed
2144

2145 2146
	break;
      case NGFI_RAU_IF4p5:
2147
	eNB->do_precoding   = 0;
2148
	eNB->do_prach       = do_prach;
2149
	eNB->fep            = NULL;
2150

hutch's avatar
hutch committed
2151 2152
	eNB->td             = ulsch_decoding_data;//(single_thread_flag==1) ? ulsch_decoding_data_2thread : ulsch_decoding_data;
	eNB->te             = dlsch_encoding;//(single_thread_flag==1) ? dlsch_encoding_2threads : dlsch_encoding;
2153
	eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX;
2154
	eNB->proc_tx        = proc_tx_high;
2155 2156
	eNB->tx_fh          = tx_fh_if4p5; 
	eNB->rx_fh          = rx_fh_if4p5; 
Raymond Knopp's avatar
Raymond Knopp committed
2157
        eNB->fh_asynch      = (eNB->node_timing == synch_to_other) ? fh_if4p5_asynch_UL : NULL;
2158 2159
	eNB->start_rf       = NULL;
	eNB->start_if       = start_if;
Raymond Knopp's avatar
Raymond Knopp committed
2160 2161 2162

	eNB->rfdevice.host_type   = BBU_HOST;
	eNB->ifdevice.host_type   = BBU_HOST;
2163
        ret = openair0_transport_load(&eNB->ifdevice, &openair0_cfg[CC_id], eNB->eth_params);
Raymond Knopp's avatar
Raymond Knopp committed
2164 2165 2166 2167 2168
        printf("openair0_transport_init returns %d for CC_id %d\n",ret,CC_id);
        if (ret<0) {
          printf("Exiting, cannot initialize transport protocol\n");
          exit(-1);
        }
2169
	break;	
Raymond Knopp's avatar
Raymond Knopp committed
2170 2171
	malloc_IF4p5_buffer(eNB);

2172
      }
2173

2174 2175 2176 2177
      if (setup_eNB_buffers(PHY_vars_eNB_g[inst],&openair0_cfg[CC_id])!=0) {
	printf("Exiting, cannot initialize eNodeB Buffers\n");
	exit(-1);
      }
2178 2179
    }

2180
    init_eNB_proc(inst);
2181
  }
2182

2183 2184 2185
  sleep(1);
  LOG_D(HW,"[lte-softmodem.c] eNB threads created\n");
  
Raymond Knopp's avatar
Raymond Knopp committed
2186

2187 2188 2189
}


2190
void stop_eNB(int nb_inst) {
2191

2192 2193 2194 2195
  for (int inst=0;inst<nb_inst;inst++) {
    printf("Killing eNB %d processing threads\n",inst);
    kill_eNB_proc(inst);
  }
2196
}