lte-enb.c 75.8 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

/*! \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"

48 49
#include "time_utils.h"

50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
#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

65
#include "PHY/LTE_TRANSPORT/if4_tools.h"
66
#include "PHY/LTE_TRANSPORT/if5_tools.h"
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 104 105
#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
106 107
#include "T.h"

108 109 110 111 112 113 114 115 116 117
//#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;

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

#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
133
extern int transmission_mode;
134

135 136
extern int oaisim_flag;

137
//pthread_t                       main_eNB_thread;
138 139 140

time_stats_t softmodem_stats_mt; // main thread
time_stats_t softmodem_stats_hw; //  hw acquisition
knopp's avatar
knopp committed
141
time_stats_t softmodem_stats_rxtx_sf; // total tx time
142
time_stats_t softmodem_stats_rx_sf; // total rx time
143 144
//int32_t **rxdata;
//int32_t **txdata;
145

146 147
uint8_t seqno; //sequence number

148 149 150 151 152 153 154 155 156 157
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;
158
} sync_phy_proc;
159

160 161
extern double cpuf;

162 163
void exit_fun(const char* s);

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


168 169 170 171 172 173 174 175
static int recv_if_count = 0;
struct timespec start_rf_new, start_rf_prev, start_rf_prev2, end_rf;
openair0_timestamp start_rf_new_ts, start_rf_prev_ts, start_rf_prev2_ts, end_rf_ts;
extern struct timespec start_fh, start_fh_prev;
extern int start_fh_sf, start_fh_prev_sf;
struct timespec end_fh;
int end_fh_sf;

knopp's avatar
knopp committed
176
static inline void thread_top_init(char *thread_name,
177
				   int affinity,
knopp's avatar
knopp committed
178 179 180
				   uint64_t runtime,
				   uint64_t deadline,
				   uint64_t period) {
knopp's avatar
knopp committed
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200

  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
201
    exit(1);
knopp's avatar
knopp committed
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
  }

#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)
  {
219 220 221 222
    if (affinity == 0)
      CPU_SET(0,&cpuset);
    else
      for (j = 1; j < get_nprocs(); j++)
knopp's avatar
knopp committed
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
        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));
248
  sparam.sched_priority = sched_get_priority_max(SCHED_FIFO);
knopp's avatar
knopp committed
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
  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);

}

knopp's avatar
knopp committed
276
static inline void wait_sync(char *thread_name) {
knopp's avatar
knopp committed
277 278 279 280 281 282 283 284 285 286 287 288 289

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

}

290 291 292 293

void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB)
{

294
  int CC_id = phy_vars_eNB->proc.CC_id;
295 296
  unsigned int aa,slot_offset;
  //int dummy_tx_b[7680*4] __attribute__((aligned(32)));
297
  int i, tx_offset;
298
  //int slot_sizeF = (phy_vars_eNB->frame_parms.ofdm_symbol_size)* ((phy_vars_eNB->frame_parms.Ncp==1) ? 6 : 7);
299
  int len;
300
  //int slot_offset_F = (subframe<<1)*slot_sizeF;
301

302
  slot_offset = subframe*phy_vars_eNB->frame_parms.samples_per_tti;
303

304 305
  if ((subframe_select(&phy_vars_eNB->frame_parms,subframe)==SF_DL)||
      ((subframe_select(&phy_vars_eNB->frame_parms,subframe)==SF_S))) {
306 307
    //    LOG_D(HW,"Frame %d: Generating slot %d\n",frame,next_slot);

308 309
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_OFDM_MODULATION,1);

310
    do_OFDM_mod_symbol(&phy_vars_eNB->common_vars,
311 312 313
		       0,
		       subframe<<1,
		       &phy_vars_eNB->frame_parms,
Florian Kaltenberger's avatar
Florian Kaltenberger committed
314
		       phy_vars_eNB->do_precoding);
315 316
 
    // if S-subframe generate first slot only 
317 318
    if (subframe_select(&phy_vars_eNB->frame_parms,subframe) == SF_DL) {
      do_OFDM_mod_symbol(&phy_vars_eNB->common_vars,
319 320 321
			 0,
			 1+(subframe<<1),
			 &phy_vars_eNB->frame_parms,
Florian Kaltenberger's avatar
Florian Kaltenberger committed
322
			 phy_vars_eNB->do_precoding);
323 324 325 326 327 328
    }

    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_OFDM_MODULATION,0);
    

/*
329 330 331
    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],
332
                     dummy_tx_b,
333
                     phy_vars_eNB->frame_parms.ofdm_symbol_size,
334
                     6,
335
                     phy_vars_eNB->frame_parms.nb_prefix_samples,
336
                     CYCLIC_PREFIX);
337 338 339 340 341 342 343
	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);
344
      } else {
345
        normal_prefix_mod(&phy_vars_eNB->common_vars.txdataF[0][aa][slot_offset_F],
346 347
                          dummy_tx_b,
                          7,
348
                          &(phy_vars_eNB->frame_parms));
349
	// if S-subframe generate first slot only
350 351 352
	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),
353
			    7,
354
			    &(phy_vars_eNB->frame_parms));
355
      }
356
    } */
357

358
    for (aa=0; aa<phy_vars_eNB->frame_parms.nb_antennas_tx; aa++) {
359
      // if S-subframe generate first slot only
360 361
      if (subframe_select(&phy_vars_eNB->frame_parms,subframe) == SF_S)
	len = phy_vars_eNB->frame_parms.samples_per_tti>>1;
362
      else
363
	len = phy_vars_eNB->frame_parms.samples_per_tti;
364 365 366 367 368 369 370
      /*
      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;
	}*/
371 372
      for (i=0; i<len; i++) {
        tx_offset = (int)slot_offset+time_offset[aa]+i;
373

374 375
	
        if (tx_offset<0)
376
          tx_offset += LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti;
377

378 379
        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;
380

381
/*	((short*)&phy_vars_eNB->common_vars.txdata[0][aa][tx_offset])[0] = ((short*)dummy_tx_b)[2*i]<<openair0_cfg[0].iq_txshift;
382
	
383
	((short*)&phy_vars_eNB->common_vars.txdata[0][aa][tx_offset])[1] = ((short*)dummy_tx_b)[2*i+1]<<openair0_cfg[0].iq_txshift; */
384

385
	((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;
386
	
387
	((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;
388
     }
389
     // if S-subframe switch to RX in second subframe
390
     if (subframe_select(&phy_vars_eNB->frame_parms,subframe) == SF_S) {
391
       for (i=0; i<len; i++) {
392
	 phy_vars_eNB->common_vars.txdata[0][aa][tx_offset++] = 0x00010001;
393 394
       }
     }
395

396 397 398 399
     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)) && 
400
	  (subframe==0)) || (subframe==5)) {
401 402 403
       // 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++) {
404
         tx_offset = (int)slot_offset+time_offset[aa]+i-phy_vars_eNB->N_TA_offset;
Sandeep Kumar's avatar
Sandeep Kumar committed
405 406
         if (tx_offset<0)
           tx_offset += LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti;
407
	 
408 409
	 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;
410
	 
411
	 phy_vars_eNB->common_vars.txdata[0][aa][tx_offset] = 0x00000000;
412 413 414 415
       }
     }
    }
  }
416
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_SFGEN , 0 );
417 418
}

419

420
void tx_fh_if5(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) {
421
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, proc->timestamp_tx&0xffffffff );
422 423 424
  if ((eNB->frame_parms.frame_type==FDD) ||
      ((eNB->frame_parms.frame_type==TDD) &&
       (subframe_select(&eNB->frame_parms,proc->subframe_tx) != SF_UL)))    
knopp's avatar
knopp committed
425
    send_IF5(eNB, proc->timestamp_tx, proc->subframe_tx, &seqno, IF5_RRH_GW_DL);
426 427
}

428 429
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 );
430 431 432
  if ((eNB->frame_parms.frame_type==FDD) ||
      ((eNB->frame_parms.frame_type==TDD) &&
       (subframe_select(&eNB->frame_parms,proc->subframe_tx) != SF_UL)))    
knopp's avatar
knopp committed
433
    send_IF5(eNB, proc->timestamp_tx, proc->subframe_tx, &seqno, IF5_MOBIPASS); 
434 435
}

knopp's avatar
knopp committed
436
void tx_fh_if4p5(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) {
437 438 439
  if ((eNB->frame_parms.frame_type==FDD) ||
      ((eNB->frame_parms.frame_type==TDD) &&
       (subframe_select(&eNB->frame_parms,proc->subframe_tx) != SF_UL)))    
knopp's avatar
knopp committed
440
    send_IF4p5(eNB,proc->frame_tx,proc->subframe_tx, IF4p5_PDLFFT, 0);
441 442
}

Raymond Knopp's avatar
Raymond Knopp committed
443 444 445 446
void proc_tx_high0(PHY_VARS_eNB *eNB,
		   eNB_rxtx_proc_t *proc,
		   relaying_type_t r_type,
		   PHY_VARS_RN *rn) {
447

knopp's avatar
knopp committed
448 449 450
  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 );
451
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB+offset, proc->subframe_tx );
knopp's avatar
knopp committed
452

453
  phy_procedures_eNB_TX(eNB,proc,r_type,rn,1,1);
454 455 456 457 458 459 460 461 462 463 464 465 466 467

  /* 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");
  }

Raymond Knopp's avatar
Raymond Knopp committed
468 469 470 471 472 473
}

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

knopp's avatar
knopp committed
475

Raymond Knopp's avatar
Raymond Knopp committed
476 477 478 479 480 481 482 483 484 485 486 487
  // 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) {
488

Raymond Knopp's avatar
Raymond Knopp committed
489 490 491 492 493 494

  // 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 
495 496
  if (eNB->tx_fh) eNB->tx_fh(eNB,proc);

497 498 499 500 501 502 503 504 505 506 507
  /*
  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("");
  }
  */
508 509
}

Raymond Knopp's avatar
Raymond Knopp committed
510 511 512 513
void proc_tx_rru_if4p5(PHY_VARS_eNB *eNB,
		       eNB_rxtx_proc_t *proc,
		       relaying_type_t r_type,
		       PHY_VARS_RN *rn) {
514 515 516 517 518

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

knopp's avatar
knopp committed
519 520 521
  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 );
522
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB+offset, proc->subframe_tx );
knopp's avatar
knopp committed
523

524 525 526 527 528
  /// **** recv_IF4 of txdataF from RCC **** ///             
  symbol_number = 0;
  symbol_mask = 0;
  symbol_mask_full = (1<<eNB->frame_parms.symbols_per_tti)-1;
  
knopp's avatar
knopp committed
529

530 531 532 533 534 535 536 537 538
  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) {
knopp's avatar
knopp committed
539 540 541
  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 );
542
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB+offset, proc->subframe_tx );
543 544
  /// **** recv_IF5 of txdata from BBU **** ///       
  recv_IF5(eNB, &proc->timestamp_tx, proc->subframe_tx, IF5_RRH_GW_DL);
545 546
}

547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572
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);
}
Sandeep Kumar's avatar
Sandeep Kumar committed
573

knopp's avatar
knopp committed
574 575 576
static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_name) {

  start_meas(&softmodem_stats_rxtx_sf);
577

knopp's avatar
knopp committed
578 579
  // ****************************************
  // Common RX procedures subframe n
580

knopp's avatar
knopp committed
581 582
  if ((eNB->do_prach)&&((eNB->node_function != NGFI_RCC_IF4p5)))
    eNB->do_prach(eNB,proc->frame_rx,proc->subframe_rx);
583
  phy_procedures_eNB_common_RX(eNB,proc);
knopp's avatar
knopp committed
584 585 586 587 588 589 590 591 592
  
  // 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)
  // *****************************************
593
  //if (wait_CCs(proc)<0) return(-1);
knopp's avatar
knopp committed
594 595 596 597 598 599 600 601 602 603 604 605
  
  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);
}

606
/*!
knopp's avatar
knopp committed
607
 * \brief The RX UE-specific and TX thread of eNB.
608 609 610
 * \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.
 */
Sandeep Kumar's avatar
Sandeep Kumar committed
611 612
static void* eNB_thread_rxtx( void* param ) {

knopp's avatar
knopp committed
613
  static int eNB_thread_rxtx_status;
614

knopp's avatar
knopp committed
615
  eNB_rxtx_proc_t *proc = (eNB_rxtx_proc_t*)param;
616 617
  PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id];

knopp's avatar
knopp committed
618 619
  char thread_name[100];

620

621
  // set default return value
knopp's avatar
knopp committed
622
  eNB_thread_rxtx_status = 0;
623 624


knopp's avatar
knopp committed
625
  sprintf(thread_name,"RXn_TXnp4_%d\n",&eNB->proc.proc_rxtx[0] == proc ? 0 : 1);
626
  thread_top_init(thread_name,1,850000L,1000000L,2000000L);
627 628

  while (!oai_exit) {
knopp's avatar
knopp committed
629
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 );
630

knopp's avatar
knopp committed
631
    if (wait_on_condition(&proc->mutex_rxtx,&proc->cond_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) break;
632

knopp's avatar
knopp committed
633
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 1 );
634

knopp's avatar
knopp committed
635
    
636
  
637 638
    if (oai_exit) break;

639 640
    if (eNB->CC_id==0)
      if (rxtx(eNB,proc,thread_name) < 0) break;
641

knopp's avatar
knopp committed
642
  } // while !oai_exit
643

knopp's avatar
knopp committed
644
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 );
645

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

knopp's avatar
knopp committed
648 649
  eNB_thread_rxtx_status = 0;
  return &eNB_thread_rxtx_status;
650 651
}

652
#if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME)
Sandeep Kumar's avatar
Sandeep Kumar committed
653 654 655
/* Wait for eNB application initialization to be complete (eNB registration to MME) */
static void wait_system_ready (char *message, volatile int *start_flag) {
  
656
  static char *indicator[] = {".    ", "..   ", "...  ", ".... ", ".....",
Sandeep Kumar's avatar
Sandeep Kumar committed
657
			      " ....", "  ...", "   ..", "    .", "     "};
658 659 660 661 662 663 664
  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);
665
  }
666 667
  
  LOG_D(EMU,"\n");
668 669
}
#endif
670

knopp's avatar
knopp committed
671

672
// asynchronous UL with IF5 (RCC,RAU,eNodeB_BBU)
knopp's avatar
knopp committed
673 674 675 676 677
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;

678
  recv_IF5(eNB, &proc->timestamp_rx, *subframe, IF5_MOBIPASS); 
knopp's avatar
knopp committed
679

680 681 682 683 684 685 686
  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;
knopp's avatar
knopp committed
687 688
    *subframe = proc->subframe_rx;
    *frame    = proc->frame_rx; 
689
    LOG_E(PHY,"[Mobipass]timestamp_rx:%"PRId64", frame_rx %d, subframe: %d\n",proc->timestamp_rx,proc->frame_rx,proc->subframe_rx);
knopp's avatar
knopp committed
690 691 692
  }
  else {
    if (proc->subframe_rx != *subframe) {
693
        proc->first_rx++;
694
       LOG_E(PHY,"[Mobipass]timestamp:%"PRId64", subframe_rx %d is not what we expect %d, first_rx:%d\n",proc->timestamp_rx, proc->subframe_rx,*subframe, proc->first_rx);
695
      //exit_fun("Exiting");
knopp's avatar
knopp committed
696 697
    }
    if (proc->frame_rx != *frame) {
698
        proc->first_rx++;
699
       LOG_E(PHY,"[Mobipass]timestamp:%"PRId64", frame_rx %d is not what we expect %d, first_rx:%d\n",proc->timestamp_rx,proc->frame_rx,*frame, proc->first_rx);  
700
     // exit_fun("Exiting");
knopp's avatar
knopp committed
701
    }
702 703 704
    // temporary solution
      *subframe = proc->subframe_rx;
      *frame    = proc->frame_rx;
knopp's avatar
knopp committed
705
  }
706 707 708

  pthread_mutex_unlock(&proc->mutex_asynch_rxtx);

knopp's avatar
knopp committed
709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730
} // 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;
731
      proc->first_rx--;
knopp's avatar
knopp committed
732 733 734
    }
    else {
      if (proc->frame_rx != *frame) {
735
	LOG_E(PHY,"fh_if4p5_asynch_UL: frame_rx %d is not what we expect %d\n",proc->frame_rx,*frame);
knopp's avatar
knopp committed
736 737 738
	exit_fun("Exiting");
      }
      if (proc->subframe_rx != *subframe) {
739
	LOG_E(PHY,"fh_if4p5_asynch_UL: subframe_rx %d is not what we expect %d\n",proc->subframe_rx,*subframe);
knopp's avatar
knopp committed
740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762
	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); 
763 764 765
  clock_gettime( CLOCK_MONOTONIC, &end_fh);
  end_fh_sf = *subframe;
  recv_if_count = recv_if_count + 1;
766
  LOG_D(HW,"[From SF %d to SF %d] RTT_FH: %"PRId64"\n", start_fh_prev_sf, end_fh_sf, clock_difftime_ns(start_fh_prev, end_fh));
767 768

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 0 );
knopp's avatar
knopp committed
769 770 771 772

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

knopp's avatar
knopp committed
773
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_ENB, frame_tx );
774
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB, subframe_tx ); 
knopp's avatar
knopp committed
775

knopp's avatar
knopp committed
776 777 778 779 780 781 782
  if (proc->first_tx != 0) {
    *subframe = subframe_tx;
    *frame    = frame_tx;
    proc->first_tx = 0;
  }
  else {
    if (subframe_tx != *subframe) {
783
      LOG_E(PHY,"fh_if5_asynch_DL: subframe_tx %d is not what we expect %d\n",subframe_tx,*subframe);
knopp's avatar
knopp committed
784 785 786
      exit_fun("Exiting");
    }
    if (frame_tx != *frame) { 
787
      LOG_E(PHY,"fh_if5_asynch_DL: frame_tx %d is not what we expect %d\n",frame_tx,*frame);
knopp's avatar
knopp committed
788 789 790 791 792 793 794 795 796 797 798
      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;
799
  uint32_t symbol_number,symbol_mask_full;
knopp's avatar
knopp committed
800 801 802 803
  int subframe_tx,frame_tx;

  symbol_number = 0;

knopp's avatar
knopp committed
804
  LOG_D(PHY,"fh_asynch_DL_IF4p5: in, frame %d, subframe %d\n",*frame,*subframe);
805 806 807 808 809 810 811 812 813 814 815

  // 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;
      }
    }
  }
knopp's avatar
knopp committed
816 817 818

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

819
  symbol_mask_full = ((subframe_select(fp,*subframe) == SF_S) ? (1<<fp->dl_symbols_in_S_subframe) : (1<<fp->symbols_per_tti))-1;
knopp's avatar
knopp committed
820 821 822 823 824 825
  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;
knopp's avatar
knopp committed
826
      proc->frame_offset = frame_tx - proc->frame_tx;
knopp's avatar
knopp committed
827 828
      symbol_mask_full = ((subframe_select(fp,*subframe) == SF_S) ? (1<<fp->dl_symbols_in_S_subframe) : (1<<fp->symbols_per_tti))-1;

knopp's avatar
knopp committed
829 830 831
    }
    else {
      if (frame_tx != *frame) {
832
	LOG_E(PHY,"fh_if4p5_asynch_DL: frame_tx %d is not what we expect %d\n",frame_tx,*frame);
knopp's avatar
knopp committed
833 834 835
	exit_fun("Exiting");
      }
      if (subframe_tx != *subframe) {
836 837
	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;
knopp's avatar
knopp committed
838 839 840 841
	exit_fun("Exiting");
      }
    }
    if (packet_type == IF4p5_PDLFFT) {
842
      proc->symbol_mask[subframe_tx] =proc->symbol_mask[subframe_tx] | (1<<symbol_number);
knopp's avatar
knopp committed
843 844 845 846 847
    }
    else {
      LOG_E(PHY,"Illegal IF4p5 packet type (should only be IF4p5_PDLFFT%d\n",packet_type);
      exit_fun("Exiting");
    }
848
  } while (proc->symbol_mask[*subframe] != symbol_mask_full);    
849
  
knopp's avatar
knopp committed
850 851
  *frame = frame_tx;

knopp's avatar
knopp committed
852

knopp's avatar
knopp committed
853 854 855
  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 );

856 857
  // intialize this to zero after we're done with the subframe
  proc->symbol_mask[*subframe] = 0;
knopp's avatar
knopp committed
858
  
859
  do_OFDM_mod_rt(*subframe, eNB);
knopp's avatar
knopp committed
860 861
} 

862
/*!
863
 * \brief The Asynchronous RX/TX FH thread of RAU/RCC/eNB/RRU.
864 865 866 867
 * 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.
 */
868
static void* eNB_thread_asynch_rxtx( void* param ) {
869

870
  static int eNB_thread_asynch_rxtx_status;
Raymond Knopp's avatar
Raymond Knopp committed
871

872 873
  eNB_proc_t *proc = (eNB_proc_t*)param;
  PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id];
knopp's avatar
knopp committed
874 875


876

knopp's avatar
knopp committed
877
  int subframe=0, frame=0; 
878

879
  thread_top_init("thread_asynch",1,870000L,1000000L,1000000L);
880 881 882

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

knopp's avatar
knopp committed
883
  wait_sync("thread_asynch");
884 885 886 887

  // 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");

knopp's avatar
knopp committed
888
  wait_on_condition(&proc->mutex_asynch_rxtx,&proc->cond_asynch_rxtx,&proc->instance_cnt_asynch_rxtx,"thread_asynch");
889 890 891 892

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


knopp's avatar
knopp committed
893 894 895
  while (!oai_exit) { 
   
    if (oai_exit) break;   
896

knopp's avatar
knopp committed
897 898 899 900 901 902 903
    if (subframe==9) { 
      subframe=0;
      frame++;
      frame&=1023;
    } else {
      subframe++;
    }      
904

knopp's avatar
knopp committed
905 906 907
    if (eNB->fh_asynch) eNB->fh_asynch(eNB,&frame,&subframe);
    else AssertFatal(1==0, "Unknown eNB->node_function %d",eNB->node_function);
    
908
  }
knopp's avatar
knopp committed
909

910 911
  eNB_thread_asynch_rxtx_status=0;
  return(&eNB_thread_asynch_rxtx_status);
912
}
Sandeep Kumar's avatar
Sandeep Kumar committed
913

914

knopp's avatar
knopp committed
915 916 917 918 919 920



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

  eNB_proc_t *proc = &eNB->proc;
921 922 923 924
  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;
925
  int tx_sfoffset = (eNB->single_thread_flag == 1) ? 3 : 2;
926
  openair0_timestamp ts,old_ts;
knopp's avatar
knopp committed
927

928 929
  if (proc->first_rx==0) {
    
930
    // Transmit TX buffer based on timestamp from RX
931
    //    printf("trx_write -> USRP TS %llu (sf %d)\n", (proc->timestamp_rx+(3*fp->samples_per_tti)),(proc->subframe_rx+2)%10);
932
    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 );
933
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
934
    // prepare tx buffer pointers
knopp's avatar
knopp committed
935 936 937 938 939 940

    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)) {
941 942 943

      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]; 
knopp's avatar
knopp committed
944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964

      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); 
965 966 967
      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,
knopp's avatar
knopp committed
968
					 siglen,
969
					 fp->nb_antennas_tx,
knopp's avatar
knopp committed
970
					 flags);
971 972 973 974
      clock_gettime( CLOCK_MONOTONIC, &end_rf);    
      end_rf_ts = proc->timestamp_rx+eNB->ts_offset+(tx_sfoffset*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance;
      if (recv_if_count != 0 ) {
        recv_if_count = recv_if_count-1;
Cedric Roux's avatar
Cedric Roux committed
975 976
        LOG_D(HW,"[From Timestamp %"PRId64" to Timestamp %"PRId64"] RTT_RF: %"PRId64"; RTT_RF\n", start_rf_prev_ts, end_rf_ts, clock_difftime_ns(start_rf_prev, end_rf));
        LOG_D(HW,"[From Timestamp %"PRId64" to Timestamp %"PRId64"] RTT_RF: %"PRId64"; RTT_RF\n",start_rf_prev2_ts, end_rf_ts, clock_difftime_ns(start_rf_prev2, end_rf));
977
      }
978 979 980 981
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
      
      
      
knopp's avatar
knopp committed
982
      if (txs !=  siglen) {
983 984 985 986
	LOG_E(PHY,"TX : Timeout (sent %d/%d)\n",txs, fp->samples_per_tti);
	exit_fun( "problem transmitting samples" );
      }	
    }
987
  }
988

989 990 991 992
  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 );
993

knopp's avatar
knopp committed
994 995
  old_ts = proc->timestamp_rx;

996
  rxs = eNB->rfdevice.trx_read_func(&eNB->rfdevice,
997
				    &ts,
998 999 1000
				    rxp,
				    fp->samples_per_tti,
				    fp->nb_antennas_rx);
1001 1002 1003 1004 1005 1006
  start_rf_prev2= start_rf_prev;
  start_rf_prev2_ts= start_rf_prev_ts; 
  start_rf_prev = start_rf_new;
  start_rf_prev_ts = start_rf_new_ts;
  clock_gettime( CLOCK_MONOTONIC, &start_rf_new);
  start_rf_new_ts = ts;
1007
  LOG_D(PHY,"rx_rf: first_rx %d received ts %"PRId64" (sptti %d)\n",proc->first_rx,ts,fp->samples_per_tti);
1008
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
1009

1010 1011
  proc->timestamp_rx = ts-eNB->ts_offset;

1012
  if (rxs != fp->samples_per_tti)
knopp's avatar
knopp committed
1013
    LOG_E(PHY,"rx_rf: Asked for %d samples, got %d from USRP\n",fp->samples_per_tti,rxs);
1014

1015
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
knopp's avatar
knopp committed
1016
 
1017
  if (proc->first_rx == 1) {
knopp's avatar
knopp committed
1018
    eNB->ts_offset = proc->timestamp_rx;
1019 1020
    proc->timestamp_rx=0;
  }
knopp's avatar
knopp committed
1021
  else {
1022

knopp's avatar
knopp committed
1023
    if (proc->timestamp_rx - old_ts != fp->samples_per_tti) {
1024
      LOG_I(PHY,"rx_rf: rfdevice timing drift of %"PRId64" samples (ts_off %"PRId64")\n",proc->timestamp_rx - old_ts - fp->samples_per_tti,eNB->ts_offset);
1025
      eNB->ts_offset += (proc->timestamp_rx - old_ts - fp->samples_per_tti);
1026
      proc->timestamp_rx = ts-eNB->ts_offset;
knopp's avatar
knopp committed
1027 1028
    }
  }
1029 1030
  proc->frame_rx    = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023;
  proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10;
1031
  proc->frame_rx    = (proc->frame_rx+proc->frame_offset)&1023;
knopp's avatar
knopp committed
1032
  proc->frame_tx    = proc->frame_rx;
1033
  if (proc->subframe_rx > 5) proc->frame_tx=(proc->frame_tx+1)&1023;
knopp's avatar
knopp committed
1034 1035
  // synchronize first reception to frame 0 subframe 0

1036
  proc->timestamp_tx = proc->timestamp_rx+(4*fp->samples_per_tti);
1037
  //  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);  
1038 1039 1040
  
  if (proc->first_rx == 0) {
    if (proc->subframe_rx != *subframe){
1041
      LOG_E(PHY,"rx_rf: Received Timestamp (%"PRId64") doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->timestamp_rx,proc->subframe_rx,*subframe);
1042 1043
      exit_fun("Exiting");
    }
1044
    int f2 = (*frame+proc->frame_offset)&1023;    
knopp's avatar
knopp committed
1045
    if (proc->frame_rx != f2) {
1046
      LOG_E(PHY,"rx_rf: Received Timestamp (%"PRId64") 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);
1047 1048 1049
      exit_fun("Exiting");
    }
  } else {
1050
    proc->first_rx--;
1051 1052 1053 1054 1055 1056 1057 1058
    *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 );
  
1059 1060 1061 1062 1063
  if (rxs != fp->samples_per_tti)
    exit_fun( "problem receiving samples" );
  

  
1064 1065
}

knopp's avatar
knopp committed
1066
void rx_fh_if5(PHY_VARS_eNB *eNB,int *frame, int *subframe) {
1067 1068

  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
knopp's avatar
knopp committed
1069
  eNB_proc_t *proc = &eNB->proc;
1070 1071 1072 1073 1074 1075 1076

  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) {
Raymond Knopp's avatar
Raymond Knopp committed
1077
    if (proc->subframe_rx != *subframe){
1078
      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);
1079 1080 1081
      exit_fun("Exiting");
    }
    
Raymond Knopp's avatar
Raymond Knopp committed
1082
    if (proc->frame_rx != *frame) {
1083
      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);
1084 1085 1086
      exit_fun("Exiting");
    }
  } else {
1087
    proc->first_rx--;
Raymond Knopp's avatar
Raymond Knopp committed
1088 1089
    *frame = proc->frame_rx;
    *subframe = proc->subframe_rx;        
1090
  }      
knopp's avatar
knopp committed
1091

1092 1093


knopp's avatar
knopp committed
1094
  proc->timestamp_tx = proc->timestamp_rx +  (4*fp->samples_per_tti);
1095 1096 1097 1098 1099
  
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );

}

knopp's avatar
knopp committed
1100

1101
void rx_fh_if4p5(PHY_VARS_eNB *eNB,int *frame,int *subframe) {
1102 1103

  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
1104
  eNB_proc_t *proc = &eNB->proc;
1105
  int f,sf;
1106 1107 1108

  uint16_t packet_type;
  uint32_t symbol_number=0;
knopp's avatar
knopp committed
1109
  uint32_t symbol_mask_full;
1110

1111 1112 1113 1114
  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;
Raymond Knopp's avatar
Raymond Knopp committed
1115

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

1120
    //proc->frame_rx = (proc->frame_rx + proc->frame_offset)&1023;
1121
    if (packet_type == IF4p5_PULFFT) {
knopp's avatar
knopp committed
1122
      LOG_D(PHY,"rx_fh_if4p5: frame %d, subframe %d, PULFFT symbol %d\n",f,sf,symbol_number);
1123

knopp's avatar
knopp committed
1124
      proc->symbol_mask[sf] = proc->symbol_mask[sf] | (1<<symbol_number);
1125
    } else if (packet_type == IF4p5_PULTICK) {
1126 1127
    
      if ((proc->first_rx==0) && (f!=*frame))
knopp's avatar
knopp committed
1128
	LOG_E(PHY,"rx_fh_if4p5: PULTICK received frame %d != expected %d\n",f,*frame);
1129 1130
      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);