lte-ru.c 110 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.1  (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
 */
knopp's avatar
knopp committed
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

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

55
#include "PHY/defs_common.h"
knopp's avatar
knopp committed
56 57 58 59
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all


#include "../../ARCH/COMMON/common_lib.h"
60
#include "../../ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h"
knopp's avatar
knopp committed
61 62 63 64

#include "PHY/LTE_TRANSPORT/if4_tools.h"
#include "PHY/LTE_TRANSPORT/if5_tools.h"

65 66
#include "PHY/phy_extern.h"
#include "LAYER2/MAC/mac_extern.h"
knopp's avatar
knopp committed
67 68 69 70
#include "PHY/LTE_TRANSPORT/transport_proto.h"
#include "SCHED/sched_eNB.h"
#include "PHY/LTE_ESTIMATION/lte_estimation.h"
#include "PHY/INIT/phy_init.h"
knopp's avatar
knopp committed
71

72 73 74 75 76
#include "LAYER2/MAC/mac.h"
#include "LAYER2/MAC/mac_extern.h"
#include "LAYER2/MAC/mac_proto.h"
#include "RRC/LTE/rrc_extern.h"
#include "PHY_INTERFACE/phy_interface.h"
knopp's avatar
knopp committed
77

78
#include "common/utils/LOG/log.h"
knopp's avatar
knopp committed
79 80 81
#include "UTIL/OTG/otg_tx.h"
#include "UTIL/OTG/otg_externs.h"
#include "UTIL/MATH/oml.h"
82
#include "common/utils/LOG/vcd_signal_dumper.h"
knopp's avatar
knopp committed
83 84
#include "UTIL/OPT/opt.h"
#include "enb_config.h"
85
#include "targets/RT/USER/lte-softmodem.h" 
knopp's avatar
knopp committed
86 87
//#include "PHY/TOOLS/time_meas.h"

88 89 90 91
/* these variables have to be defined before including ENB_APP/enb_paramdef.h */
static int DEFBANDS[] = {7};
static int DEFENBS[] = {0};

92 93 94
#include "ENB_APP/enb_paramdef.h"
#include "common/config/config_userapi.h"

knopp's avatar
knopp committed
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
#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

#include "T.h"

Wang Tsu-Han's avatar
Wang Tsu-Han committed
110
#include "pdcp.h"
Wang Tsu-Han's avatar
Wang Tsu-Han committed
111

knopp's avatar
knopp committed
112
extern volatile int                    oai_exit;
113
extern int emulate_rf;
114
extern int numerology;
115
extern clock_source_t clock_source;
116
extern uint8_t dlsch_ue_select_tbl_in_use;
117
extern uint8_t nfapi_mode;
knopp's avatar
knopp committed
118

119 120
extern PARALLEL_CONF_t get_thread_parallel_conf(void);
extern WORKER_CONF_t   get_thread_worker_conf(void);
121
extern void  phy_init_RU(RU_t*);
122
extern void  phy_free_RU(RU_t*);
123

124

Robert Schmidt's avatar
Robert Schmidt committed
125
void stop_RU(int nb_ru);
126
void do_ru_sync(RU_t *ru);
knopp's avatar
knopp committed
127

128 129 130 131 132 133 134
void configure_ru(int idx,
		  void *arg);

void configure_rru(int idx,
		   void *arg);

int attach_rru(RU_t *ru);
knopp's avatar
knopp committed
135

136
int connect_rau(RU_t *ru);
knopp's avatar
knopp committed
137

138
extern uint16_t sf_ahead;
139

140 141 142 143 144
#if defined(PRE_SCD_THREAD)
void init_ru_vnf(void);
#endif


145 146 147
/*************************************************************/
/* Functions to attach and configure RRU                     */

knopp's avatar
knopp committed
148
extern void wait_eNBs(void);
149

150 151 152 153 154 155
int attach_rru(RU_t *ru) {
  
  ssize_t      msg_len,len;
  RRU_CONFIG_msg_t rru_config_msg;
  int received_capabilities=0;

knopp's avatar
knopp committed
156
  wait_eNBs();
157 158 159
  // Wait for capabilities
  while (received_capabilities==0) {
    
160
    memset((void*)&rru_config_msg,0,sizeof(rru_config_msg));
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
    rru_config_msg.type = RAU_tick; 
    rru_config_msg.len  = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE;
    LOG_I(PHY,"Sending RAU tick to RRU %d\n",ru->idx);
    AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),
		"RU %d cannot access remote radio\n",ru->idx);

    msg_len  = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_capabilities_t);

    // wait for answer with timeout  
    if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice,
					     &rru_config_msg,
					     msg_len))<0) {
      LOG_I(PHY,"Waiting for RRU %d\n",ru->idx);     
    }
    else if (rru_config_msg.type == RRU_capabilities) {
      AssertFatal(rru_config_msg.len==msg_len,"Received capabilities with incorrect length (%d!=%d)\n",(int)rru_config_msg.len,(int)msg_len);
      LOG_I(PHY,"Received capabilities from RRU %d (len %d/%d, num_bands %d,max_pdschReferenceSignalPower %d, max_rxgain %d, nb_tx %d, nb_rx %d)\n",ru->idx,
	    (int)rru_config_msg.len,(int)msg_len,
	     ((RRU_capabilities_t*)&rru_config_msg.msg[0])->num_bands,
	     ((RRU_capabilities_t*)&rru_config_msg.msg[0])->max_pdschReferenceSignalPower[0],
	     ((RRU_capabilities_t*)&rru_config_msg.msg[0])->max_rxgain[0],
	     ((RRU_capabilities_t*)&rru_config_msg.msg[0])->nb_tx[0],
	     ((RRU_capabilities_t*)&rru_config_msg.msg[0])->nb_rx[0]);
      received_capabilities=1;
    }
    else {
      LOG_E(PHY,"Received incorrect message %d from RRU %d\n",rru_config_msg.type,ru->idx); 
    }
  }
  configure_ru(ru->idx,
	       (RRU_capabilities_t *)&rru_config_msg.msg[0]);
		    
  rru_config_msg.type = RRU_config;
  rru_config_msg.len  = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_config_t);
  LOG_I(PHY,"Sending Configuration to RRU %d (num_bands %d,band0 %d,txfreq %u,rxfreq %u,att_tx %d,att_rx %d,N_RB_DL %d,N_RB_UL %d,3/4FS %d, prach_FO %d, prach_CI %d)\n",ru->idx,
	((RRU_config_t *)&rru_config_msg.msg[0])->num_bands,
	((RRU_config_t *)&rru_config_msg.msg[0])->band_list[0],
	((RRU_config_t *)&rru_config_msg.msg[0])->tx_freq[0],
	((RRU_config_t *)&rru_config_msg.msg[0])->rx_freq[0],
	((RRU_config_t *)&rru_config_msg.msg[0])->att_tx[0],
	((RRU_config_t *)&rru_config_msg.msg[0])->att_rx[0],
	((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_DL[0],
	((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_UL[0],
	((RRU_config_t *)&rru_config_msg.msg[0])->threequarter_fs[0],
	((RRU_config_t *)&rru_config_msg.msg[0])->prach_FreqOffset[0],
	((RRU_config_t *)&rru_config_msg.msg[0])->prach_ConfigIndex[0]);

208

209 210 211 212 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 238 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 266
  AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),
	      "RU %d failed send configuration to remote radio\n",ru->idx);

  return 0;
}

int connect_rau(RU_t *ru) {

  RRU_CONFIG_msg_t   rru_config_msg;
  ssize_t	     msg_len;
  int                tick_received          = 0;
  int                configuration_received = 0;
  RRU_capabilities_t *cap;
  int                i;
  int                len;

  // wait for RAU_tick
  while (tick_received == 0) {

    msg_len  = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE;

    if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice,
					     &rru_config_msg,
					     msg_len))<0) {
      LOG_I(PHY,"Waiting for RAU\n");     
    }
    else {
      if (rru_config_msg.type == RAU_tick) {
	LOG_I(PHY,"Tick received from RAU\n");
	tick_received = 1;
      }
      else LOG_E(PHY,"Received erroneous message (%d)from RAU, expected RAU_tick\n",rru_config_msg.type);
    }
  }

  // send capabilities

  rru_config_msg.type = RRU_capabilities; 
  rru_config_msg.len  = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_capabilities_t);
  cap                 = (RRU_capabilities_t*)&rru_config_msg.msg[0];
  LOG_I(PHY,"Sending Capabilities (len %d, num_bands %d,max_pdschReferenceSignalPower %d, max_rxgain %d, nb_tx %d, nb_rx %d)\n",
	(int)rru_config_msg.len,ru->num_bands,ru->max_pdschReferenceSignalPower,ru->max_rxgain,ru->nb_tx,ru->nb_rx);
  switch (ru->function) {
  case NGFI_RRU_IF4p5:
    cap->FH_fmt                                   = OAI_IF4p5_only;
    break;
  case NGFI_RRU_IF5:
    cap->FH_fmt                                   = OAI_IF5_only;
    break;
  case MBP_RRU_IF5:
    cap->FH_fmt                                   = MBP_IF5;
    break;
  default:
    AssertFatal(1==0,"RU_function is unknown %d\n",RC.ru[0]->function);
    break;
  }
  cap->num_bands                                  = ru->num_bands;
  for (i=0;i<ru->num_bands;i++) {
267 268
	LOG_I(PHY,"Band %d: nb_rx %d nb_tx %d pdschReferenceSignalPower %d rxgain %d\n",
	ru->band[i],ru->nb_rx,ru->nb_tx,ru->max_pdschReferenceSignalPower,ru->max_rxgain);
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
    cap->band_list[i]                             = ru->band[i];
    cap->nb_rx[i]                                 = ru->nb_rx;
    cap->nb_tx[i]                                 = ru->nb_tx;
    cap->max_pdschReferenceSignalPower[i]         = ru->max_pdschReferenceSignalPower;
    cap->max_rxgain[i]                            = ru->max_rxgain;
  }
  AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),
	      "RU %d failed send capabilities to RAU\n",ru->idx);

  // wait for configuration
  rru_config_msg.len  = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_config_t);
  while (configuration_received == 0) {

    if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice,
					     &rru_config_msg,
					     rru_config_msg.len))<0) {
      LOG_I(PHY,"Waiting for configuration from RAU\n");     
    }    
    else {
      LOG_I(PHY,"Configuration received from RAU  (num_bands %d,band0 %d,txfreq %u,rxfreq %u,att_tx %d,att_rx %d,N_RB_DL %d,N_RB_UL %d,3/4FS %d, prach_FO %d, prach_CI %d)\n",
	    ((RRU_config_t *)&rru_config_msg.msg[0])->num_bands,
	    ((RRU_config_t *)&rru_config_msg.msg[0])->band_list[0],
	    ((RRU_config_t *)&rru_config_msg.msg[0])->tx_freq[0],
	    ((RRU_config_t *)&rru_config_msg.msg[0])->rx_freq[0],
	    ((RRU_config_t *)&rru_config_msg.msg[0])->att_tx[0],
	    ((RRU_config_t *)&rru_config_msg.msg[0])->att_rx[0],
	    ((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_DL[0],
	    ((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_UL[0],
	    ((RRU_config_t *)&rru_config_msg.msg[0])->threequarter_fs[0],
	    ((RRU_config_t *)&rru_config_msg.msg[0])->prach_FreqOffset[0],
	    ((RRU_config_t *)&rru_config_msg.msg[0])->prach_ConfigIndex[0]);
      
      configure_rru(ru->idx,
		    (void*)&rru_config_msg.msg[0]);
      configuration_received = 1;
    }
  }
  return 0;
}
knopp's avatar
knopp committed
308 309 310 311 312
/*************************************************************/
/* Southbound Fronthaul functions, RCC/RAU                   */

// southbound IF5 fronthaul for 16-bit OAI format
static inline void fh_if5_south_out(RU_t *ru) {
313 314
  if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );
  send_IF5(ru, ru->proc.timestamp_tx, ru->proc.subframe_tx, &ru->seqno, IF5_RRH_GW_DL);
knopp's avatar
knopp committed
315 316 317 318
}

// southbound IF5 fronthaul for Mobipass packet format
static inline void fh_if5_mobipass_south_out(RU_t *ru) {
319 320
  if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );
  send_IF5(ru, ru->proc.timestamp_tx, ru->proc.subframe_tx, &ru->seqno, IF5_MOBIPASS); 
knopp's avatar
knopp committed
321 322 323 324
}

// southbound IF4p5 fronthaul
static inline void fh_if4p5_south_out(RU_t *ru) {
325
  if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );
326
  LOG_D(PHY,"Sending IF4p5 for frame %d subframe %d\n",ru->proc.frame_tx,ru->proc.subframe_tx);
327 328
  if (subframe_select(&ru->frame_parms,ru->proc.subframe_tx)!=SF_UL) 
    send_IF4p5(ru,ru->proc.frame_tx, ru->proc.subframe_tx, IF4p5_PDLFFT);
knopp's avatar
knopp committed
329 330 331 332 333 334 335 336 337
}

/*************************************************************/
/* Input Fronthaul from south RCC/RAU                        */

// Synchronous if5 from south 
void fh_if5_south_in(RU_t *ru,int *frame, int *subframe) {

  LTE_DL_FRAME_PARMS *fp = &ru->frame_parms;
338
  RU_proc_t *proc = &ru->proc;
knopp's avatar
knopp committed
339

340
  recv_IF5(ru, &proc->timestamp_rx, *subframe, IF5_RRH_GW_UL); 
knopp's avatar
knopp committed
341 342 343 344 345 346

  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) {
    if (proc->subframe_rx != *subframe){
347
      LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,*subframe);
knopp's avatar
knopp committed
348 349 350 351
      exit_fun("Exiting");
    }
    
    if (proc->frame_rx != *frame) {
352
      LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,*frame);
knopp's avatar
knopp committed
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368
      exit_fun("Exiting");
    }
  } else {
    proc->first_rx = 0;
    *frame = proc->frame_rx;
    *subframe = proc->subframe_rx;        
  }      
  
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );

}

// Synchronous if4p5 from south 
void fh_if4p5_south_in(RU_t *ru,int *frame,int *subframe) {

  LTE_DL_FRAME_PARMS *fp = &ru->frame_parms;
369 370
  RU_proc_t *proc = &ru->proc;
  int f,sf;
knopp's avatar
knopp committed
371 372 373 374


  uint16_t packet_type;
  uint32_t symbol_number=0;
375 376 377 378 379 380
  uint32_t symbol_mask_full;

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

382
  AssertFatal(proc->symbol_mask[*subframe]==0,"rx_fh_if4p5: proc->symbol_mask[%d] = %x\n",*subframe,proc->symbol_mask[*subframe]);
knopp's avatar
knopp committed
383
  do {   // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!!
384
    recv_IF4p5(ru, &f, &sf, &packet_type, &symbol_number);
knopp's avatar
knopp committed
385

386 387 388 389
    if (packet_type == IF4p5_PULFFT) proc->symbol_mask[sf] = proc->symbol_mask[sf] | (1<<symbol_number);
    else if (packet_type == IF4p5_PULTICK) {           
      if ((proc->first_rx==0) && (f!=*frame)) LOG_E(PHY,"rx_fh_if4p5: PULTICK received frame %d != expected %d\n",f,*frame);       
      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);       
390
      break;     
391
      
knopp's avatar
knopp committed
392
    } else if (packet_type == IF4p5_PRACH) {
393
      // nothing in RU for RAU
knopp's avatar
knopp committed
394
    }
395
    LOG_D(PHY,"rx_fh_if4p5: subframe %d symbol mask %x\n",*subframe,proc->symbol_mask[*subframe]);
396
  } while(proc->symbol_mask[*subframe] != symbol_mask_full);    
knopp's avatar
knopp committed
397 398

  //caculate timestamp_rx, timestamp_tx based on frame and subframe
399 400
  proc->subframe_rx  = sf;
  proc->frame_rx     = f;
401
  proc->timestamp_rx = ((proc->frame_rx * 10)  + proc->subframe_rx ) * fp->samples_per_tti ;
402
  //  proc->timestamp_tx = proc->timestamp_rx +  (4*fp->samples_per_tti);
403 404
  proc->subframe_tx  = (sf+sf_ahead)%10;
  proc->frame_tx     = (sf>(9-sf_ahead)) ? (f+1)&1023 : f;
knopp's avatar
knopp committed
405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
 
  if (proc->first_rx == 0) {
    if (proc->subframe_rx != *subframe){
      LOG_E(PHY,"Received Timestamp (IF4p5) doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,*subframe);
      exit_fun("Exiting");
    }
    if (proc->frame_rx != *frame) {
      LOG_E(PHY,"Received Timestamp (IF4p5) doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,*frame);
      exit_fun("Exiting");
    }
  } else {
    proc->first_rx = 0;
    *frame = proc->frame_rx;
    *subframe = proc->subframe_rx;        
  }
420

421 422 423 424 425 426 427
  if (ru == RC.ru[0]) {
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_RU, f );
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_RU, sf );
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, proc->frame_tx );
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_RU, proc->subframe_tx );
  }

428
  proc->symbol_mask[sf] = 0;  
knopp's avatar
knopp committed
429
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
430 431
  LOG_D(PHY,"RU %d: fh_if4p5_south_in sleeping ...\n",ru->idx);
  usleep(100);
knopp's avatar
knopp committed
432 433 434 435 436 437
}

// Dummy FH from south for getting synchronization from master RU
void fh_slave_south_in(RU_t *ru,int *frame,int *subframe) {
  // This case is for synchronization to another thread
  // it just waits for an external event.  The actual rx_fh is handle by the asynchronous RX thread
438
  RU_proc_t *proc=&ru->proc;
knopp's avatar
knopp committed
439 440 441 442 443 444 445 446 447

  if (wait_on_condition(&proc->mutex_FH,&proc->cond_FH,&proc->instance_cnt_FH,"fh_slave_south_in") < 0)
    return;

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

  
}

448 449
// asynchronous inbound if5 fronthaul from south (Mobipass)
void fh_if5_south_asynch_in_mobipass(RU_t *ru,int *frame,int *subframe) {
knopp's avatar
knopp committed
450

451 452
  RU_proc_t *proc       = &ru->proc;
  LTE_DL_FRAME_PARMS *fp = &ru->frame_parms;
knopp's avatar
knopp committed
453

454 455 456 457 458 459
  recv_IF5(ru, &proc->timestamp_rx, *subframe, IF5_MOBIPASS); 
  pthread_mutex_lock(&proc->mutex_asynch_rxtx);
  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;
knopp's avatar
knopp committed
460

461 462
  proc->subframe_rx = (proc->timestamp_rx/fp->samples_per_tti)%10;
  proc->frame_rx    = (proc->timestamp_rx/(10*fp->samples_per_tti))&1023;
knopp's avatar
knopp committed
463

464 465
  if (proc->first_rx == 1) {
    proc->first_rx =2;
knopp's avatar
knopp committed
466 467
    *subframe = proc->subframe_rx;
    *frame    = proc->frame_rx; 
468
    LOG_E(PHY,"[Mobipass]timestamp_rx:%llu, frame_rx %d, subframe: %d\n",(unsigned long long int)proc->timestamp_rx,proc->frame_rx,proc->subframe_rx);
knopp's avatar
knopp committed
469 470 471
  }
  else {
    if (proc->subframe_rx != *subframe) {
472 473 474
        proc->first_rx++;
	LOG_E(PHY,"[Mobipass]timestamp:%llu, subframe_rx %d is not what we expect %d, first_rx:%d\n",(unsigned long long int)proc->timestamp_rx, proc->subframe_rx,*subframe, proc->first_rx);
      //exit_fun("Exiting");
knopp's avatar
knopp committed
475 476
    }
    if (proc->frame_rx != *frame) {
477 478 479
        proc->first_rx++;
       LOG_E(PHY,"[Mobipass]timestamp:%llu, frame_rx %d is not what we expect %d, first_rx:%d\n",(unsigned long long int)proc->timestamp_rx,proc->frame_rx,*frame, proc->first_rx);  
     // exit_fun("Exiting");
knopp's avatar
knopp committed
480
    }
481 482 483
    // temporary solution
      *subframe = proc->subframe_rx;
      *frame    = proc->frame_rx;
knopp's avatar
knopp committed
484
  }
485 486 487 488

  pthread_mutex_unlock(&proc->mutex_asynch_rxtx);


knopp's avatar
knopp committed
489 490 491 492 493 494
} // eNodeB_3GPP_BBU 

// asynchronous inbound if4p5 fronthaul from south
void fh_if4p5_south_asynch_in(RU_t *ru,int *frame,int *subframe) {

  LTE_DL_FRAME_PARMS *fp = &ru->frame_parms;
495
  RU_proc_t *proc       = &ru->proc;
knopp's avatar
knopp committed
496 497

  uint16_t packet_type;
knopp's avatar
knopp committed
498
  uint32_t symbol_number,symbol_mask,prach_rx;
499
  uint32_t got_prach_info=0;
knopp's avatar
knopp committed
500 501

  symbol_number = 0;
502 503
  symbol_mask   = (1<<fp->symbols_per_tti)-1;
  prach_rx      = 0;
knopp's avatar
knopp committed
504 505 506

  do {   // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!!
    recv_IF4p5(ru, &proc->frame_rx, &proc->subframe_rx, &packet_type, &symbol_number);
507 508 509 510 511
    // grab first prach information for this new subframe
    if (got_prach_info==0) {
      prach_rx       = is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx);
      got_prach_info = 1;
    }
knopp's avatar
knopp committed
512 513 514 515 516 517 518 519 520 521 522 523 524 525 526
    if (proc->first_rx != 0) {
      *frame = proc->frame_rx;
      *subframe = proc->subframe_rx;
      proc->first_rx = 0;
    }
    else {
      if (proc->frame_rx != *frame) {
	LOG_E(PHY,"frame_rx %d is not what we expect %d\n",proc->frame_rx,*frame);
	exit_fun("Exiting");
      }
      if (proc->subframe_rx != *subframe) {
	LOG_E(PHY,"subframe_rx %d is not what we expect %d\n",proc->subframe_rx,*subframe);
	exit_fun("Exiting");
      }
    }
527 528
    if      (packet_type == IF4p5_PULFFT)       symbol_mask &= (~(1<<symbol_number));
    else if (packet_type == IF4p5_PRACH)        prach_rx    &= (~0x1);
529
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
530 531 532 533 534 535
    else if (packet_type == IF4p5_PRACH_BR_CE0) prach_rx    &= (~0x2);
    else if (packet_type == IF4p5_PRACH_BR_CE1) prach_rx    &= (~0x4);
    else if (packet_type == IF4p5_PRACH_BR_CE2) prach_rx    &= (~0x8);
    else if (packet_type == IF4p5_PRACH_BR_CE3) prach_rx    &= (~0x10);
#endif
  } while( (symbol_mask > 0) || (prach_rx >0));   // haven't received all PUSCH symbols and PRACH information 
knopp's avatar
knopp committed
536 537 538 539 540 541 542 543 544 545 546
} 





/*************************************************************/
/* Input Fronthaul from North RRU                            */
  
// RRU IF4p5 TX fronthaul receiver. Assumes an if_device on input and if or rf device on output 
// receives one subframe's worth of IF4p5 OFDM symbols and OFDM modulates
547
void fh_if4p5_north_in(RU_t *ru,int *frame,int *subframe) {
knopp's avatar
knopp committed
548 549 550 551 552

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

553

knopp's avatar
knopp committed
554 555 556 557 558 559
  /// **** incoming IF4p5 from remote RCC/RAU **** ///             
  symbol_number = 0;
  symbol_mask = 0;
  symbol_mask_full = (1<<ru->frame_parms.symbols_per_tti)-1;
  
  do { 
560
    recv_IF4p5(ru, frame, subframe, &packet_type, &symbol_number);
knopp's avatar
knopp committed
561 562 563
    symbol_mask = symbol_mask | (1<<symbol_number);
  } while (symbol_mask != symbol_mask_full); 

564 565
  // dump VCD output for first RU in list
  if (ru == RC.ru[0]) {
566 567
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, *frame );
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_RU, *subframe );
knopp's avatar
knopp committed
568 569 570 571 572 573
  }
}

void fh_if5_north_asynch_in(RU_t *ru,int *frame,int *subframe) {

  LTE_DL_FRAME_PARMS *fp = &ru->frame_parms;
574
  RU_proc_t *proc        = &ru->proc;
knopp's avatar
knopp committed
575 576 577 578 579 580 581 582 583 584 585 586 587 588 589
  int subframe_tx,frame_tx;
  openair0_timestamp timestamp_tx;

  recv_IF5(ru, &timestamp_tx, *subframe, IF5_RRH_GW_DL); 
      //      printf("Received subframe %d (TS %llu) from RCC\n",subframe_tx,timestamp_tx);

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

  if (proc->first_tx != 0) {
    *subframe = subframe_tx;
    *frame    = frame_tx;
    proc->first_tx = 0;
  }
  else {
590 591 592 593
    AssertFatal(subframe_tx == *subframe,
                "subframe_tx %d is not what we expect %d\n",subframe_tx,*subframe);
    AssertFatal(frame_tx == *frame, 
                "frame_tx %d is not what we expect %d\n",frame_tx,*frame);
knopp's avatar
knopp committed
594 595 596 597 598 599
  }
}

void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *subframe) {

  LTE_DL_FRAME_PARMS *fp = &ru->frame_parms;
600
  RU_proc_t *proc        = &ru->proc;
knopp's avatar
knopp committed
601 602 603 604 605

  uint16_t packet_type;
  uint32_t symbol_number,symbol_mask,symbol_mask_full;
  int subframe_tx,frame_tx;

Cedric Roux's avatar
Cedric Roux committed
606
  LOG_D(PHY, "%s(ru:%p frame, subframe)\n", __FUNCTION__, ru);
knopp's avatar
knopp committed
607 608
  symbol_number = 0;
  symbol_mask = 0;
609
  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
610 611
  do {   
    recv_IF4p5(ru, &frame_tx, &subframe_tx, &packet_type, &symbol_number);
612
    if ((subframe_select(fp,subframe_tx) == SF_DL) && (symbol_number == 0)) start_meas(&ru->rx_fhaul);
613 614
    LOG_D(PHY,"subframe %d (%d): frame %d, subframe %d, symbol %d\n",
         *subframe,subframe_select(fp,*subframe),frame_tx,subframe_tx,symbol_number);
knopp's avatar
knopp committed
615 616 617 618
    if (proc->first_tx != 0) {
      *frame    = frame_tx;
      *subframe = subframe_tx;
      proc->first_tx = 0;
619
      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
620 621
    }
    else {
622 623 624 625
      AssertFatal(frame_tx == *frame,
	          "frame_tx %d is not what we expect %d\n",frame_tx,*frame);
      AssertFatal(subframe_tx == *subframe,
		  "subframe_tx %d is not what we expect %d\n",subframe_tx,*subframe);
knopp's avatar
knopp committed
626 627 628 629
    }
    if (packet_type == IF4p5_PDLFFT) {
      symbol_mask = symbol_mask | (1<<symbol_number);
    }
630
    else AssertFatal(1==0,"Illegal IF4p5 packet type (should only be IF4p5_PDLFFT%d\n",packet_type);
knopp's avatar
knopp committed
631
  } while (symbol_mask != symbol_mask_full);    
632

633
  if (subframe_select(fp,subframe_tx) == SF_DL) stop_meas(&ru->rx_fhaul);
634

635 636 637 638
  proc->subframe_tx  = subframe_tx;
  proc->frame_tx     = frame_tx;

  if ((frame_tx == 0)&&(subframe_tx == 0)) proc->frame_tx_unwrap += 1024;
639

640 641
  proc->timestamp_tx = ((((uint64_t)frame_tx + (uint64_t)proc->frame_tx_unwrap) * 10) + (uint64_t)subframe_tx) * (uint64_t)fp->samples_per_tti;

642
  LOG_D(PHY,"RU %d/%d TST %llu, frame %d, subframe %d\n",ru->idx,0,(long long unsigned int)proc->timestamp_tx,frame_tx,subframe_tx);
643 644 645 646 647
    // dump VCD output for first RU in list
  if (ru == RC.ru[0]) {
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame_tx );
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_RU, subframe_tx );
  }
648

649 650
  if (ru->feptx_ofdm) ru->feptx_ofdm(ru);
  if (ru->fh_south_out) ru->fh_south_out(ru);
knopp's avatar
knopp committed
651 652
} 

653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670
void fh_if5_north_out(RU_t *ru) {

  RU_proc_t *proc=&ru->proc;
  uint8_t seqno=0;

  /// **** send_IF5 of rxdata to BBU **** ///       
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 );  
  send_IF5(ru, proc->timestamp_rx, proc->subframe_rx, &seqno, IF5_RRH_GW_UL);
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 );          

}

// RRU IF4p5 northbound interface (RX)
void fh_if4p5_north_out(RU_t *ru) {

  RU_proc_t *proc=&ru->proc;
  LTE_DL_FRAME_PARMS *fp = &ru->frame_parms;
  const int subframe     = proc->subframe_rx;
671
  if (ru->idx==0) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_RU, proc->subframe_rx );
672 673 674

  if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) {
    /// **** in TDD during DL send_IF4 of ULTICK to RCC **** ///
675
    send_IF4p5(ru, proc->frame_rx, proc->subframe_rx, IF4p5_PULTICK);
676 677 678
    return;
  }

679 680 681
  start_meas(&ru->tx_fhaul);
  send_IF4p5(ru, proc->frame_rx, proc->subframe_rx, IF4p5_PULFFT);
  stop_meas(&ru->tx_fhaul);
682 683

}
684

Wang Tsu-Han's avatar
Wang Tsu-Han committed
685 686 687 688 689 690 691 692 693 694 695 696 697
/* add fail safe for late command */
typedef enum {
	STATE_BURST_NORMAL = 0,
	STATE_BURST_TERMINATE = 1,
	STATE_BURST_STOP_1 = 2,
	STATE_BURST_STOP_2 = 3,
	STATE_BURST_RESTART = 4,
} late_control_e;

volatile late_control_e late_control=STATE_BURST_NORMAL;

/* add fail safe for late command end */

698 699 700 701
static void* emulatedRF_thread(void* param) {
  RU_proc_t *proc = (RU_proc_t *) param;
  int microsec = 500; // length of time to sleep, in miliseconds
  struct timespec req = {0};
702
  int numerology = get_softmodem_params()->numerology;
703
  req.tv_sec = 0;
Eurecom's avatar
Eurecom committed
704
  req.tv_nsec = (numerology>0)? ((microsec * 1000L)/numerology):(microsec * 1000L)*2;
705 706 707 708 709 710 711 712 713 714 715
  cpu_set_t cpuset;
  CPU_SET(1,&cpuset);
  pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
  
  int policy;
  struct sched_param sparam;
  memset(&sparam, 0, sizeof(sparam));
  sparam.sched_priority = sched_get_priority_max(SCHED_FIFO);
  policy = SCHED_FIFO ; 
  pthread_setschedparam(pthread_self(), policy, &sparam);
  
716 717 718
  wait_sync("emulatedRF_thread");
  while(!oai_exit){
    nanosleep(&req, (struct timespec *)NULL);
719 720 721 722 723
    if(proc->emulate_rf_busy )
    {
      LOG_E(PHY,"rf being delayed in emulated RF\n");
    }
    proc->emulate_rf_busy = 1;
724 725 726 727 728 729 730 731
    pthread_mutex_lock(&proc->mutex_emulateRF);
    ++proc->instance_cnt_emulateRF;
    pthread_mutex_unlock(&proc->mutex_emulateRF);
    pthread_cond_signal(&proc->cond_emulateRF);
  }
  return 0;
}

knopp's avatar
knopp committed
732 733
void rx_rf(RU_t *ru,int *frame,int *subframe) {

734
  RU_proc_t *proc = &ru->proc;
knopp's avatar
knopp committed
735
  LTE_DL_FRAME_PARMS *fp = &ru->frame_parms;
736
  void *rxp[ru->nb_rx];
737
  unsigned int rxs;
knopp's avatar
knopp committed
738
  int i;
739
  openair0_timestamp ts=0,old_ts=0;
knopp's avatar
knopp committed
740
    
741
  for (i=0; i<ru->nb_rx; i++)
742
    rxp[i] = (void*)&ru->common.rxdata[i][*subframe*fp->samples_per_tti];
743

knopp's avatar
knopp committed
744 745
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 );

746
  old_ts = proc->timestamp_rx;
747
  if(get_softmodem_params()->emulate_rf){
748 749 750 751 752 753
    wait_on_condition(&proc->mutex_emulateRF,&proc->cond_emulateRF,&proc->instance_cnt_emulateRF,"emulatedRF_thread");
    release_thread(&proc->mutex_emulateRF,&proc->instance_cnt_emulateRF,"emulatedRF_thread");
    rxs = fp->samples_per_tti;
  }
  else{
    rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
754
				   &ts,
knopp's avatar
knopp committed
755 756
				   rxp,
				   fp->samples_per_tti,
757
				   ru->nb_rx);
758
  }
knopp's avatar
knopp committed
759 760 761
  
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
 
762
  proc->timestamp_rx = ts-ru->ts_offset;
763

Wang Tsu-Han's avatar
Wang Tsu-Han committed
764
//  AssertFatal(rxs == fp->samples_per_tti,
765
//	      "rx_rf: Asked for %d samples, got %d from SDR\n",fp->samples_per_tti,rxs);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
766
  if(rxs != fp->samples_per_tti){
767
    LOG_E(PHY,"rx_rf: Asked for %d samples, got %d from SDR\n",fp->samples_per_tti,rxs);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
768 769
    late_control=STATE_BURST_TERMINATE;
  }
770 771

  if (proc->first_rx == 1) {
772
    ru->ts_offset = proc->timestamp_rx;
773 774 775 776
    proc->timestamp_rx = 0;
  }
  else {
    if (proc->timestamp_rx - old_ts != fp->samples_per_tti) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
777
      //LOG_I(PHY,"rx_rf: rfdevice timing drift of %"PRId64" samples (ts_off %"PRId64")\n",proc->timestamp_rx - old_ts - fp->samples_per_tti,ru->ts_offset);
778
      ru->ts_offset += (proc->timestamp_rx - old_ts - fp->samples_per_tti);
779
      proc->timestamp_rx = ts-ru->ts_offset;
780 781 782 783 784
    }

  }
  proc->frame_rx     = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023;
  proc->subframe_rx  = (proc->timestamp_rx / fp->samples_per_tti)%10;
knopp's avatar
knopp committed
785 786
  // synchronize first reception to frame 0 subframe 0

Wang Tsu-Han's avatar
Wang Tsu-Han committed
787 788 789 790 791 792 793 794 795 796
#ifdef PHY_TX_THREAD
  proc->timestamp_phy_tx = proc->timestamp_rx+((sf_ahead-1)*fp->samples_per_tti);
  proc->subframe_phy_tx  = (proc->subframe_rx+(sf_ahead-1))%10;  
  proc->frame_phy_tx     = (proc->subframe_rx>(9-(sf_ahead-1))) ? (proc->frame_rx+1)&1023 : proc->frame_rx;
#else
  proc->timestamp_tx = proc->timestamp_rx+(sf_ahead*fp->samples_per_tti);
  proc->subframe_tx  = (proc->subframe_rx+sf_ahead)%10;
  proc->frame_tx     = (proc->subframe_rx>(9-sf_ahead)) ? (proc->frame_rx+1)&1023 : proc->frame_rx;
#endif

797 798 799
  //proc->timestamp_tx = proc->timestamp_rx+(sf_ahead*fp->samples_per_tti);
  //proc->subframe_tx  = (proc->subframe_rx+sf_ahead)%10;
  //proc->frame_tx     = (proc->subframe_rx>(9-sf_ahead)) ? (proc->frame_rx+1)&1023 : proc->frame_rx;
800 801 802 803 804 805
  
  LOG_D(PHY,"RU %d/%d TS %llu (off %d), frame %d, subframe %d\n",
	ru->idx, 
	0, 
	(unsigned long long int)proc->timestamp_rx,
	(int)ru->ts_offset,proc->frame_rx,proc->subframe_rx);
806

807 808 809 810 811
    // dump VCD output for first RU in list
  if (ru == RC.ru[0]) {
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_RU, proc->frame_rx );
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_RU, proc->subframe_rx );
  }
knopp's avatar
knopp committed
812 813 814
  
  if (proc->first_rx == 0) {
    if (proc->subframe_rx != *subframe){
815
      LOG_E(PHY,"Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",(long long unsigned int)proc->timestamp_rx,proc->subframe_rx,*subframe);
knopp's avatar
knopp committed
816 817 818 819
      exit_fun("Exiting");
    }
    
    if (proc->frame_rx != *frame) {
820
      LOG_E(PHY,"Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",(long long unsigned int)proc->timestamp_rx,proc->frame_rx,*frame);
knopp's avatar
knopp committed
821 822 823 824 825 826 827 828 829 830
      exit_fun("Exiting");
    }
  } else {
    proc->first_rx = 0;
    *frame = proc->frame_rx;
    *subframe = proc->subframe_rx;        
  }
  
  //printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",ru->timestamp_rx,proc->frame_rx,frame,proc->subframe_rx,subframe);
  
831
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
knopp's avatar
knopp committed
832 833
  
  if (rxs != fp->samples_per_tti)
834
  {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
835 836 837
#if defined(USRP_REC_PLAY)
    exit_fun("Exiting IQ record/playback");
#else    
838
    //exit_fun( "problem receiving samples" );
Cedric Roux's avatar
Cedric Roux committed
839
    LOG_E(PHY, "problem receiving samples");
Wang Tsu-Han's avatar
Wang Tsu-Han committed
840
#endif    
841
  }
knopp's avatar
knopp committed
842 843 844
}


845 846 847 848
void tx_rf(RU_t *ru) {

  RU_proc_t *proc = &ru->proc;
  LTE_DL_FRAME_PARMS *fp = &ru->frame_parms;
849
  void *txp[ru->nb_tx]; 
850 851 852
  unsigned int txs;
  int i;

Cedric Roux's avatar
Cedric Roux committed
853 854 855
  T(T_ENB_PHY_OUTPUT_SIGNAL, T_INT(0), T_INT(0), T_INT(proc->frame_tx), T_INT(proc->subframe_tx),
    T_INT(0), T_BUFFER(&ru->common.txdata[0][proc->subframe_tx * fp->samples_per_tti], fp->samples_per_tti * 4));

856 857 858
  lte_subframe_t SF_type     = subframe_select(fp,proc->subframe_tx%10);
  lte_subframe_t prevSF_type = subframe_select(fp,(proc->subframe_tx+9)%10);
  lte_subframe_t nextSF_type = subframe_select(fp,(proc->subframe_tx+1)%10);
859 860
  int sf_extension = 0;

861 862 863 864 865 866 867 868 869 870 871 872
  if ((SF_type == SF_DL) ||
      (SF_type == SF_S)) {
    
    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) &&
873
	(nextSF_type == SF_DL)) { 
874
      flags = 2; // start of burst
Wang Tsu-Han's avatar
Wang Tsu-Han committed
875
      sf_extension = ru->N_TA_offset;
876
    }
877 878 879 880
    
    if ((fp->frame_type == TDD) &&
	(SF_type == SF_DL)&&
	(prevSF_type == SF_UL) &&
881
	(nextSF_type == SF_UL)) {
882
      flags = 4; // start of burst and end of burst (only one DL SF between two UL)
Wang Tsu-Han's avatar
Wang Tsu-Han committed
883
      sf_extension = ru->N_TA_offset;
884
    } 
Wang Tsu-Han's avatar
Wang Tsu-Han committed
885 886 887 888 889 890 891 892 893 894
#if defined(__x86_64) || defined(__i386__)
#ifdef __AVX2__
  sf_extension = (sf_extension)&0xfffffff8;
#else
  sf_extension = (sf_extension)&0xfffffffc;
#endif
#elif defined(__arm__)
  sf_extension = (sf_extension)&0xfffffffc;
#endif
    
895 896 897
    for (i=0; i<ru->nb_tx; i++)
      txp[i] = (void*)&ru->common.txdata[i][(proc->subframe_tx*fp->samples_per_tti)-sf_extension];

Wang Tsu-Han's avatar
Wang Tsu-Han committed
898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928
    /* add fail safe for late command */
    if(late_control!=STATE_BURST_NORMAL){//stop burst
      switch (late_control) {
      case STATE_BURST_TERMINATE:
        flags=10; // end of burst and no time spec
        late_control=STATE_BURST_STOP_1;
        break;
      
      case STATE_BURST_STOP_1:
        flags=0; // no send
        late_control=STATE_BURST_STOP_2;
        return;//no send
       break;
      
      case STATE_BURST_STOP_2:
        flags=0; // no send
        late_control=STATE_BURST_RESTART;
        return;//no send
        break;
      
      case STATE_BURST_RESTART:
        flags=2; // start burst
        late_control=STATE_BURST_NORMAL;
        break;
      default:
        LOG_D(PHY,"[TXPATH] RU %d late_control %d not implemented\n",ru->idx, late_control);
      break;
      }
    }
    /* add fail safe for late command end */

knopp's avatar
knopp committed
929 930
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, proc->frame_tx );
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_RU, proc->subframe_tx );
Wang Tsu-Han's avatar
Wang Tsu-Han committed
931

932 933 934 935 936
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (proc->timestamp_tx-ru->openair0_cfg.tx_sample_advance)&0xffffffff );
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
    // prepare tx buffer pointers
    
    txs = ru->rfdevice.trx_write_func(&ru->rfdevice,
937
				      proc->timestamp_tx+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension,
938
				      txp,
939
				      siglen+sf_extension,
940 941 942 943
				      ru->nb_tx,
				      flags);
    
    LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, unwrapped_frame %d, subframe %d\n",ru->idx,
knopp's avatar
knopp committed
944
	  (long long unsigned int)proc->timestamp_tx,proc->frame_tx,proc->frame_tx_unwrap,proc->subframe_tx);
945
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
946
    
947
    
Wang Tsu-Han's avatar
Wang Tsu-Han committed
948 949 950 951 952
//    AssertFatal(txs ==  siglen+sf_extension,"TX : Timeout (sent %d/%d)\n",txs, siglen);
    if( (txs !=  siglen+sf_extension) && (late_control==STATE_BURST_NORMAL) ){ /* add fail safe for late command */
      late_control=STATE_BURST_TERMINATE;
      LOG_E(PHY,"TX : Timeout (sent %d/%d) state =%d\n",txs, siglen,late_control);
    }
953
  }
954 955 956
}


knopp's avatar
knopp committed
957 958 959
/*!
 * \brief The Asynchronous RX/TX FH thread of RAU/RCC/eNB/RRU.
 * This handles the RX FH for an asynchronous RRU/UE
960
 * \param param is a \ref L1_proc_t structure which contains the info what to process.
knopp's avatar
knopp committed
961 962 963 964 965 966
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
static void* ru_thread_asynch_rxtx( void* param ) {

  static int ru_thread_asynch_rxtx_status;

967 968 969
  RU_t *ru         = (RU_t*)param;
  RU_proc_t *proc  = &ru->proc;

knopp's avatar
knopp committed
970 971 972 973


  int subframe=0, frame=0; 

974
  thread_top_init("ru_thread_asynch_rxtx",1,870000,1000000,1000000);
knopp's avatar
knopp committed
975 976 977

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

978
  wait_sync("ru_thread_asynch_rxtx");
knopp's avatar
knopp committed
979 980

  // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe
981
  printf( "waiting for devices (ru_thread_asynch_rx)\n");
knopp's avatar
knopp committed
982 983 984

  wait_on_condition(&proc->mutex_asynch_rxtx,&proc->cond_asynch_rxtx,&proc->instance_cnt_asynch_rxtx,"thread_asynch");

985
  printf( "devices ok (ru_thread_asynch_rx)\n");
knopp's avatar
knopp committed
986 987 988 989 990 991 992 993 994 995 996 997 998


  while (!oai_exit) { 
   
    if (oai_exit) break;   

    if (subframe==9) { 
      subframe=0;
      frame++;
      frame&=1023;
    } else {
      subframe++;
    }      
999
    LOG_D(PHY,"ru_thread_asynch_rxtx: Waiting on incoming fronthaul\n");
1000
	// asynchronous receive from south (Mobipass)
1001 1002
    if (ru->fh_south_asynch_in) ru->fh_south_asynch_in(ru,&frame,&subframe);
    // asynchronous receive from north (RRU IF4/IF5)
1003 1004 1005 1006
    else if (ru->fh_north_asynch_in) {
       if (subframe_select(&ru->frame_parms,subframe)!=SF_UL)
         ru->fh_north_asynch_in(ru,&frame,&subframe);
    }
1007
    else AssertFatal(1==0,"Unknown function in ru_thread_asynch_rxtx\n");
knopp's avatar
knopp committed
1008 1009 1010 1011 1012 1013 1014 1015 1016
  }

  ru_thread_asynch_rxtx_status=0;
  return(&ru_thread_asynch_rxtx_status);
}




1017
void wakeup_slaves(RU_proc_t *proc) {
knopp's avatar
knopp committed
1018 1019 1020 1021 1022 1023 1024 1025

  int i;
  struct timespec wait;
  
  wait.tv_sec=0;
  wait.tv_nsec=5000000L;
  
  for (i=0;i<proc->num_slaves;i++) {
1026
    RU_proc_t *slave_proc = proc->slave_proc[i];
knopp's avatar
knopp committed
1027 1028 1029
    // wake up slave FH thread
    // lock the FH mutex and make sure the thread is ready
    if (pthread_mutex_timedlock(&slave_proc->mutex_FH,&wait) != 0) {
1030
      LOG_E( PHY, "ERROR pthread_mutex_lock for RU %d slave %d (IC %d)\n",proc->ru->idx,slave_proc->ru->idx,slave_proc->instance_cnt_FH);
knopp's avatar
knopp committed
1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045
      exit_fun( "error locking mutex_rxtx" );
      break;
    }
    
    int cnt_slave            = ++slave_proc->instance_cnt_FH;
    slave_proc->frame_rx     = proc->frame_rx;
    slave_proc->subframe_rx  = proc->subframe_rx;
    slave_proc->timestamp_rx = proc->timestamp_rx;
    slave_proc->timestamp_tx = proc->timestamp_tx; 

    pthread_mutex_unlock( &slave_proc->mutex_FH );
    
    if (cnt_slave == 0) {
      // the thread was presumably waiting where it should and can now be woken up
      if (pthread_cond_signal(&slave_proc->cond_FH) != 0) {
1046
	LOG_E( PHY, "ERROR pthread_cond_signal for RU %d, slave RU %d\n",proc->ru->idx,slave_proc->ru->idx);
knopp's avatar
knopp committed
1047 1048 1049 1050
          exit_fun( "ERROR pthread_cond_signal" );
	  break;
      }
    } else {
1051
      LOG_W( PHY,"[RU] Frame %d, slave %d thread busy!! (cnt_FH %i)\n",slave_proc->frame_rx,slave_proc->ru->idx, cnt_slave);
knopp's avatar
knopp committed
1052 1053 1054 1055 1056 1057 1058 1059
      exit_fun( "FH thread busy" );
      break;
    }             
  }
}

/*!
 * \brief The prach receive thread of RU.
1060
 * \param param is a \ref RU_proc_t structure which contains the info what to process.
knopp's avatar
knopp committed
1061 1062 1063
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
static void* ru_thread_prach( void* param ) {
1064

knopp's avatar
knopp committed
1065 1066
  static int ru_thread_prach_status;

1067 1068
  RU_t *ru        = (RU_t*)param;
  RU_proc_t *proc = (RU_proc_t*)&ru->proc;
knopp's avatar
knopp committed
1069 1070

  // set default return value
1071
  ru_thread_prach_status = 0;
knopp's avatar
knopp committed
1072

1073
  thread_top_init("ru_thread_prach",1,500000,1000000,20000000);
1074
  //wait_sync("ru_thread_prach");
knopp's avatar
knopp committed
1075

1076 1077 1078 1079 1080 1081
  while (RC.ru_mask>0) {
    usleep(1e6);
    LOG_I(PHY,"%s() RACH waiting for RU to be configured\n", __FUNCTION__);
  }
  LOG_I(PHY,"%s() RU configured - RACH processing thread running\n", __FUNCTION__);

knopp's avatar
knopp committed
1082 1083
  while (!oai_exit) {
    
1084
    if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break;
1085
    if (oai_exit) break;
1086
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 1 );      
1087 1088
    if (ru->eNB_list[0]){
      prach_procedures(
1089
        ru->eNB_list[0]
1090
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1091
        ,0
1092
#endif
1093
        );
1094 1095 1096 1097 1098 1099 1100 1101 1102
    }
    else {
       rx_prach(NULL,
  	        ru,
	        NULL,
                NULL,
                NULL,
                proc->frame_prach,
                0
1103
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1104 1105 1106 1107
	        ,0
#endif
	        );
    } 
1108
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 );      
1109
    if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break;
knopp's avatar
knopp committed
1110 1111
  }

1112 1113 1114 1115 1116 1117
  LOG_I(PHY, "Exiting RU thread PRACH\n");

  ru_thread_prach_status = 0;
  return &ru_thread_prach_status;
}

1118
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1119 1120 1121 1122 1123 1124 1125 1126 1127 1128
static void* ru_thread_prach_br( void* param ) {

  static int ru_thread_prach_status;

  RU_t *ru        = (RU_t*)param;
  RU_proc_t *proc = (RU_proc_t*)&ru->proc;

  // set default return value
  ru_thread_prach_status = 0;

1129
  thread_top_init("ru_thread_prach_br",1,500000,1000000,20000000);
1130
  //wait_sync("ru_thread_prach_br");
1131 1132 1133 1134

  while (!oai_exit) {
    
    if (wait_on_condition(&proc->mutex_prach_br,&proc->cond_prach_br,&proc->instance_cnt_prach_br,"ru_prach_thread_br") < 0) break;
1135
    if (oai_exit) break;
1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147
    rx_prach(NULL,
	     ru,
	     NULL,
             NULL,
             NULL,
             proc->frame_prach_br,
             0,
	     1);
    if (release_thread(&proc->mutex_prach_br,&proc->instance_cnt_prach_br,"ru_prach_thread_br") < 0) break;
  }

  LOG_I(PHY, "Exiting RU thread PRACH BR\n");
knopp's avatar
knopp committed
1148

1149 1150
  ru_thread_prach_status = 0;
  return &ru_thread_prach_status;
knopp's avatar
knopp committed
1151
}
1152
#endif
knopp's avatar
knopp committed
1153

1154
int wakeup_synch(RU_t *ru){
knopp's avatar
knopp committed
1155

1156 1157 1158 1159
  struct timespec wait;
  
  wait.tv_sec=0;
  wait.tv_nsec=5000000L;
knopp's avatar
knopp committed
1160

1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187
  // wake up synch thread
  // lock the synch mutex and make sure the thread is ready
  if (pthread_mutex_timedlock(&ru->proc.mutex_synch,&wait) != 0) {
    LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for RU synch thread (IC %d)\n", ru->proc.instance_cnt_synch );
    exit_fun( "error locking mutex_synch" );
    return(-1);
  }
  
  ++ru->proc.instance_cnt_synch;
  
  // the thread can now be woken up
  if (pthread_cond_signal(&ru->proc.cond_synch) != 0) {
    LOG_E( PHY, "[RU] ERROR pthread_cond_signal for RU synch thread\n");
    exit_fun( "ERROR pthread_cond_signal" );
    return(-1);
  }
  
  pthread_mutex_unlock( &ru->proc.mutex_synch );

  return(0);
}

void do_ru_synch(RU_t *ru) {

  LTE_DL_FRAME_PARMS *fp  = &ru->frame_parms;
  RU_proc_t *proc         = &ru->proc;
  int i;
knopp's avatar
knopp committed
1188 1189
  void *rxp[2],*rxp2[2];
  int32_t dummy_rx[ru->nb_rx][fp->samples_per_tti] __attribute__((aligned(32)));
1190 1191
  int rxs;
  int ic;
knopp's avatar
knopp committed
1192 1193 1194

  // initialize the synchronization buffer to the common_vars.rxdata
  for (int i=0;i<ru->nb_rx;i++)
1195
    rxp[i] = &ru->common.rxdata[i][0];
knopp's avatar
knopp committed
1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211

  double temp_freq1 = ru->rfdevice.openair0_cfg->rx_freq[0];
  double temp_freq2 = ru->rfdevice.openair0_cfg->tx_freq[0];
  for (i=0;i<4;i++) {
    ru->rfdevice.openair0_cfg->rx_freq[i] = ru->rfdevice.openair0_cfg->tx_freq[i];
    ru->rfdevice.openair0_cfg->tx_freq[i] = temp_freq1;
  }
  ru->rfdevice.trx_set_freq_func(&ru->rfdevice,ru->rfdevice.openair0_cfg,0);
  
  while ((ru->in_synch ==0)&&(!oai_exit)) {
    // read in frame
    rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
				     &(proc->timestamp_rx),
				     rxp,
				     fp->samples_per_tti*10,
				     ru->nb_rx);
1212 1213
    if (rxs != fp->samples_per_tti*10) LOG_E(PHY,"requested %d samples, got %d\n",fp->samples_per_tti*10,rxs);
 
knopp's avatar
knopp committed
1214 1215 1216 1217 1218 1219 1220 1221
    // wakeup synchronization processing thread
    wakeup_synch(ru);
    ic=0;
    
    while ((ic>=0)&&(!oai_exit)) {
      // continuously read in frames, 1ms at a time, 
      // until we are done with the synchronization procedure
      
1222
      for (i=0; i<ru->nb_rx; i++)
knopp's avatar
knopp committed
1223 1224 1225 1226 1227 1228 1229
	rxp2[i] = (void*)&dummy_rx[i][0];
      for (i=0;i<10;i++)
	rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
					 &(proc->timestamp_rx),
					 rxp2,
					 fp->samples_per_tti,
					 ru->nb_rx);
1230 1231 1232
      pthread_mutex_lock(&ru->proc.mutex_synch);
      ic = ru->proc.instance_cnt_synch;
      pthread_mutex_unlock(&ru->proc.mutex_synch);
knopp's avatar
knopp committed
1233 1234 1235 1236 1237 1238 1239 1240
    } // ic>=0
  } // in_synch==0
    // read in rx_offset samples
  LOG_I(PHY,"Resynchronizing by %d samples\n",ru->rx_offset);
  rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
				   &(proc->timestamp_rx),
				   rxp,
				   ru->rx_offset,
1241
				   ru->nb_rx);
knopp's avatar
knopp committed
1242 1243 1244 1245 1246 1247 1248 1249 1250
  for (i=0;i<4;i++) {
    ru->rfdevice.openair0_cfg->rx_freq[i] = temp_freq1;
    ru->rfdevice.openair0_cfg->tx_freq[i] = temp_freq2;
  }

  ru->rfdevice.trx_set_freq_func(&ru->rfdevice,ru->rfdevice.openair0_cfg,0);

}

1251 1252


1253
void wakeup_L1s(RU_t *ru) {
1254 1255 1256 1257

  int i;
  PHY_VARS_eNB **eNB_list = ru->eNB_list;

1258
  LOG_D(PHY,"wakeup_L1s (num %d) for RU %d ru->eNB_top:%p\n",ru->num_eNB,ru->idx, ru->eNB_top);
1259

1260

1261
  if (ru->num_eNB==1 && ru->eNB_top!=0 && get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD) {
1262
    // call eNB function directly
1263
  
1264 1265
    char string[20];
    sprintf(string,"Incoming RU %d",ru->idx);
Cedric Roux's avatar
Cedric Roux committed
1266
    LOG_D(PHY,"RU %d Call eNB_top\n",ru->idx);
1267
    ru->eNB_top(eNB_list[0],ru->proc.frame_rx,ru->proc.subframe_rx,string,ru);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1268
    ru->proc.emulate_rf_busy = 0;
1269 1270 1271
  }
  else {

1272 1273
    LOG_D(PHY,"ru->num_eNB:%d\n", ru->num_eNB);

1274
    for (i=0;i<ru->num_eNB;i++)
1275
    {
1276
      LOG_D(PHY,"ru->wakeup_rxtx:%p\n", ru->wakeup_rxtx);
1277
      if (ru->wakeup_rxtx!=0 && ru->wakeup_rxtx(eNB_list[i],ru) < 0)
1278
      {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1279
        LOG_E(PHY,"could not wakeup eNB rxtx process for subframe %d\n", ru->proc.subframe_rx);
1280
      }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1281
      ru->proc.emulate_rf_busy = 0;
1282
    }
1283 1284 1285
  }
}

1286
static inline int wakeup_prach_ru(RU_t *ru) {
1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297

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

  if (pthread_mutex_timedlock(&ru->proc.mutex_prach,&wait) !=0) {
    LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for RU prach thread (IC %d)\n", ru->proc.instance_cnt_prach);
    exit_fun( "error locking mutex_rxtx" );
    return(-1);
  }
1298 1299 1300 1301
  if (ru->proc.instance_cnt_prach==-1) {
    ++ru->proc.instance_cnt_prach;
    ru->proc.frame_prach    = ru->proc.frame_rx;
    ru->proc.subframe_prach = ru->proc.subframe_rx;
1302

1303
    // DJP - think prach_procedures() is looking at eNB frame_prach
1304 1305 1306 1307
    if (ru->eNB_list[0]) {
      ru->eNB_list[0]->proc.frame_prach = ru->proc.frame_rx;
      ru->eNB_list[0]->proc.subframe_prach = ru->proc.subframe_rx;
    }
knopp's avatar
knopp committed
1308
    LOG_D(PHY,"RU %d: waking up PRACH thread\n",ru->idx);
1309 1310
    // the thread can now be woken up
    AssertFatal(pthread_cond_signal(&ru->proc.cond_prach) == 0, "ERROR pthread_cond_signal for RU prach thread\n");
1311
  }
1312
  else LOG_W(PHY,"RU prach thread busy, skipping\n");
1313 1314 1315 1316 1317
  pthread_mutex_unlock( &ru->proc.mutex_prach );

  return(0);
}

1318
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346
static inline int wakeup_prach_ru_br(RU_t *ru) {

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

  if (pthread_mutex_timedlock(&ru->proc.mutex_prach_br,&wait) !=0) {
    LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for RU prach thread BR (IC %d)\n", ru->proc.instance_cnt_prach_br);
    exit_fun( "error locking mutex_rxtx" );
    return(-1);
  }
  if (ru->proc.instance_cnt_prach_br==-1) {
    ++ru->proc.instance_cnt_prach_br;
    ru->proc.frame_prach_br    = ru->proc.frame_rx;
    ru->proc.subframe_prach_br = ru->proc.subframe_rx;

    LOG_D(PHY,"RU %d: waking up PRACH thread\n",ru->idx);
    // the thread can now be woken up
    AssertFatal(pthread_cond_signal(&ru->proc.cond_prach_br) == 0, "ERROR pthread_cond_signal for RU prach thread BR\n");
  }
  else LOG_W(PHY,"RU prach thread busy, skipping\n");
  pthread_mutex_unlock( &ru->proc.mutex_prach_br );

  return(0);
}
#endif

knopp's avatar
knopp committed
1347 1348 1349 1350 1351 1352 1353
// this is for RU with local RF unit
void fill_rf_config(RU_t *ru, char *rf_config_file) {

  int i;

  LTE_DL_FRAME_PARMS *fp   = &ru->frame_parms;
  openair0_config_t *cfg   = &ru->openair0_cfg;
1354
  //printf("////////////////numerology in config = %d\n",numerology);
1355
  int numerology = get_softmodem_params()->numerology;
knopp's avatar
knopp committed
1356
  if(fp->N_RB_DL == 100) {
1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382
    if(numerology == 0){
      if (fp->threequarter_fs) {
        cfg->sample_rate=23.04e6;
        cfg->samples_per_frame = 230400; 
        cfg->tx_bw = 10e6;
        cfg->rx_bw = 10e6;
      }
      else {
        cfg->sample_rate=30.72e6;
        cfg->samples_per_frame = 307200; 
        cfg->tx_bw = 10e6;
        cfg->rx_bw = 10e6;
      }
	}else if(numerology == 1){
	  cfg->sample_rate=61.44e6;
      cfg->samples_per_frame = 307200; 
      cfg->tx_bw = 20e6;
      cfg->rx_bw = 20e6;
	}else if(numerology == 2){
	  cfg->sample_rate=122.88e6;
      cfg->samples_per_frame = 307200; 
      cfg->tx_bw = 40e6;
      cfg->rx_bw = 40e6;
	}else{
	  printf("Wrong input for numerology %d\n setting to 20MHz normal CP configuration",numerology);
	  cfg->sample_rate=30.72e6;
knopp's avatar
knopp committed
1383 1384 1385
      cfg->samples_per_frame = 307200; 
      cfg->tx_bw = 10e6;
      cfg->rx_bw = 10e6;
1386
	}
knopp's avatar
knopp committed
1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413
  } else if(fp->N_RB_DL == 50) {
    cfg->sample_rate=15.36e6;
    cfg->samples_per_frame = 153600;
    cfg->tx_bw = 5e6;
    cfg->rx_bw = 5e6;
  } else if (fp->N_RB_DL == 25) {
    cfg->sample_rate=7.68e6;
    cfg->samples_per_frame = 76800;
    cfg->tx_bw = 2.5e6;
    cfg->rx_bw = 2.5e6;
  } else if (fp->N_RB_DL == 6) {
    cfg->sample_rate=1.92e6;
    cfg->samples_per_frame = 19200;
    cfg->tx_bw = 1.5e6;
    cfg->rx_bw = 1.5e6;
  }
  else AssertFatal(1==0,"Unknown N_RB_DL %d\n",fp->N_RB_DL);

  if (fp->frame_type==TDD)
    cfg->duplex_mode = duplex_mode_TDD;
  else //FDD
    cfg->duplex_mode = duplex_mode_FDD;

  cfg->Mod_id = 0;
  cfg->num_rb_dl=fp->N_RB_DL;
  cfg->tx_num_channels=ru->nb_tx;
  cfg->rx_num_channels=ru->nb_rx;
1414
  cfg->clock_source=get_softmodem_params()->clock_source;
1415

knopp's avatar
knopp committed
1416 1417 1418 1419 1420
  for (i=0; i<ru->nb_tx; i++) {
    
    cfg->tx_freq[i] = (double)fp->dl_CarrierFreq;
    cfg->rx_freq[i] = (double)fp->ul_CarrierFreq;

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1421 1422
    cfg->tx_gain[i] = (double)ru->att_tx;
    cfg->rx_gain[i] = ru->max_rxgain-(double)ru->att_rx;
knopp's avatar
knopp committed
1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454

    cfg->configFilename = rf_config_file;
    printf("channel %d, Setting tx_gain offset %f, rx_gain offset %f, tx_freq %f, rx_freq %f\n",
	   i, cfg->tx_gain[i],
	   cfg->rx_gain[i],
	   cfg->tx_freq[i],
	   cfg->rx_freq[i]);
  }
}

/* this function maps the RU tx and rx buffers to the available rf chains.
   Each rf chain is is addressed by the card number and the chain on the card. The
   rf_map specifies for each antenna port, on which rf chain the mapping should start. Multiple
   antennas are mapped to successive RF chains on the same card. */
int setup_RU_buffers(RU_t *ru) {

  int i,j; 
  int card,ant;

  //uint16_t N_TA_offset = 0;

  LTE_DL_FRAME_PARMS *frame_parms;
  
  if (ru) {
    frame_parms = &ru->frame_parms;
    printf("setup_RU_buffers: frame_parms = %p\n",frame_parms);
  } else {
    printf("RU[%d] not initialized\n", ru->idx);
    return(-1);
  }
  
  
1455 1456 1457 1458
  if (frame_parms->frame_type == TDD) {
    if      (frame_parms->N_RB_DL == 100) ru->N_TA_offset = 624;
    else if (frame_parms->N_RB_DL == 50)  ru->N_TA_offset = 624/2;
    else if (frame_parms->N_RB_DL == 25)  ru->N_TA_offset = 624/4;
1459 1460 1461 1462 1463 1464
#if BASIC_SIMULATOR
    /* this is required for the basic simulator in TDD mode
     * TODO: find a proper cleaner solution
     */
    ru->N_TA_offset = 0;
#endif
1465
  } 
knopp's avatar
knopp committed
1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503
  if (ru->openair0_cfg.mmapped_dma == 1) {
    // replace RX signal buffers with mmaped HW versions
    
    for (i=0; i<ru->nb_rx; i++) {
      card = i/4;
      ant = i%4;
      printf("Mapping RU id %d, rx_ant %d, on card %d, chain %d\n",ru->idx,i,ru->rf_map.card+card, ru->rf_map.chain+ant);
      free(ru->common.rxdata[i]);
      ru->common.rxdata[i] = ru->openair0_cfg.rxbase<