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
bugfix    
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
knopp's avatar
knopp committed
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


knopp's avatar
knopp committed
166
static inline void thread_top_init(char *thread_name,
167
				   int affinity,
knopp's avatar
knopp committed
168
169
170
				   uint64_t runtime,
				   uint64_t deadline,
				   uint64_t period) {
knopp's avatar
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
small2    
laurent committed
191
    exit(1);
knopp's avatar
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++)
knopp's avatar
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);
knopp's avatar
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);

}

knopp's avatar
knopp committed
266
static inline void wait_sync(char *thread_name) {
knopp's avatar
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;
Sandeep Kumar's avatar
Sandeep Kumar committed
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) {
Raymond Knopp's avatar
Raymond Knopp committed
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)))    
knopp's avatar
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)))    
knopp's avatar
knopp committed
422
    send_IF5(eNB, proc->timestamp_tx, proc->subframe_tx, &seqno, IF5_MOBIPASS); 
423
424
}

knopp's avatar
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)))    
knopp's avatar
knopp committed
429
    send_IF4p5(eNB,proc->frame_tx,proc->subframe_tx, IF4p5_PDLFFT, 0);
430
431
}

Raymond Knopp's avatar
Raymond Knopp committed
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

knopp's avatar
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 );
knopp's avatar
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");
  }

Raymond Knopp's avatar
Raymond Knopp committed
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

knopp's avatar
knopp committed
464

Raymond Knopp's avatar
Raymond Knopp committed
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

Raymond Knopp's avatar
Raymond Knopp committed
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
}

Raymond Knopp's avatar
Raymond Knopp committed
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;

knopp's avatar
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 );
knopp's avatar
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;
  
knopp's avatar
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) {
knopp's avatar
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);
}
Sandeep Kumar's avatar
Sandeep Kumar committed
562

knopp's avatar
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

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

knopp's avatar
knopp committed
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);
knopp's avatar
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);
knopp's avatar
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
/*!
knopp's avatar
knopp committed
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.
 */
Sandeep Kumar's avatar
Sandeep Kumar committed
600
601
static void* eNB_thread_rxtx( void* param ) {

knopp's avatar
knopp committed
602
  static int eNB_thread_rxtx_status;
603

knopp's avatar
knopp committed
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];

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

609

610
  // set default return value
knopp's avatar
knopp committed
611
  eNB_thread_rxtx_status = 0;
612
613


knopp's avatar
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) {
knopp's avatar
knopp committed
618
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 );
619

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

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

knopp's avatar
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

knopp's avatar
knopp committed
631
  } // while !oai_exit
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), 0 );
634

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

knopp's avatar
knopp committed
637
638
  eNB_thread_rxtx_status = 0;
  return &eNB_thread_rxtx_status;
639
640
}

641
#if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME)
Sandeep Kumar's avatar
Sandeep Kumar committed
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[] = {".    ", "..   ", "...  ", ".... ", ".....",
Sandeep Kumar's avatar
Sandeep Kumar committed
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

knopp's avatar
knopp committed
660

661
// asynchronous UL with IF5 (RCC,RAU,eNodeB_BBU)
knopp's avatar
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); 
knopp's avatar
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;
knopp's avatar
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);
knopp's avatar
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");
knopp's avatar
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");
knopp's avatar
knopp committed
690
    }
691
692
693
    // temporary solution
      *subframe = proc->subframe_rx;
      *frame    = proc->frame_rx;
knopp's avatar
knopp committed
694
  }
695
696
697

  pthread_mutex_unlock(&proc->mutex_asynch_rxtx);

knopp's avatar
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--;
knopp's avatar
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);
knopp's avatar
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);
knopp's avatar
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); 
knopp's avatar
knopp committed
752
  //printf("Received subframe %d (TS %llu) from RCC\n",subframe_tx,timestamp_tx);
knopp's avatar
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;

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

knopp's avatar
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);
knopp's avatar
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);
knopp's avatar
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;
knopp's avatar
knopp committed
784
785
786
787
  int subframe_tx,frame_tx;

  symbol_number = 0;

knopp's avatar
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;
      }
    }
  }
knopp's avatar
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;
knopp's avatar
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;
knopp's avatar
knopp committed
810
      proc->frame_offset = frame_tx - proc->frame_tx;
knopp's avatar
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;

knopp's avatar
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);
knopp's avatar
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;
knopp's avatar
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);
knopp's avatar
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);    

knopp's avatar
knopp committed
834
835
  *frame = frame_tx;

knopp's avatar
knopp committed
836

knopp's avatar
knopp committed
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;
knopp's avatar
knopp committed
842
  
843
  do_OFDM_mod_rt(*subframe, eNB);
knopp's avatar
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;
Raymond Knopp's avatar
Raymond Knopp committed
855

856
857
  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
858
859


860

knopp's avatar
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

knopp's avatar
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");

knopp's avatar
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");


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

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

knopp's avatar
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
  }
knopp's avatar
knopp committed
893

894
895
  eNB_thread_asynch_rxtx_status=0;
  return(&eNB_thread_asynch_rxtx_status);
896
}
Sandeep Kumar's avatar
Sandeep Kumar committed
897

898

knopp's avatar
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;
knopp's avatar
knopp committed
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
knopp's avatar
knopp committed
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]; 
knopp's avatar
knopp committed
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,
knopp's avatar
knopp committed
951
					 siglen,
952
					 fp->nb_antennas_tx,
knopp's avatar
knopp committed
953
					 flags);
954
955
956
957
958
      
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
      
      
      
knopp's avatar
knopp committed
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

knopp's avatar
knopp committed
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);
Raymond Knopp's avatar
Raymond Knopp committed
978

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

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

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

knopp's avatar
knopp committed
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;
knopp's avatar
knopp committed
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;
knopp's avatar
knopp committed
1001
  proc->frame_tx    = proc->frame_rx;
1002
  if (proc->subframe_rx > 5) proc->frame_tx=(proc->frame_tx+1)&1023;
knopp's avatar
knopp committed
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;    
knopp's avatar
knopp committed
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 );
  
Raymond Knopp's avatar
Raymond Knopp committed
1028
1029
1030
1031
1032
  if (rxs != fp->samples_per_tti)
    exit_fun( "problem receiving samples" );
  

  
1033
1034
}

knopp's avatar
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;
knopp's avatar
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) {
Raymond Knopp's avatar
Raymond Knopp committed
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");
    }
    
Raymond Knopp's avatar
Raymond Knopp committed
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--;
Raymond Knopp's avatar
Raymond Knopp committed
1057
1058
    *frame = proc->frame_rx;
    *subframe = proc->subframe_rx;        
1059
  }      
knopp's avatar
knopp committed
1060

1061
1062


knopp's avatar
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 );

}

knopp's avatar
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;
knopp's avatar
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;
Raymond Knopp's avatar
Raymond Knopp committed
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) {
knopp's avatar
knopp committed
1091
      LOG_D(PHY,"rx_fh_if4p5: frame %d, subframe %d, PULFFT symbol %d\n",f,sf,symbol_number);
1092

knopp's avatar
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))