lte-ru.c 117 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
 */
Raymond Knopp's avatar
Raymond Knopp committed
21 22
/*! \file lte-ru.c
 * \brief Top-level threads for RU entity
Raymond Knopp's avatar
Raymond Knopp committed
23
 * \author R. Knopp, F. Kaltenberger, Navid Nikaein
Raymond Knopp's avatar
Raymond Knopp committed
24
 * \date 2019
Raymond Knopp's avatar
Raymond Knopp committed
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
 * \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"

54
#include "PHY/defs_common.h"
Raymond Knopp's avatar
Raymond Knopp committed
55 56 57 58
#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"
59
#include "../../ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h"
Raymond Knopp's avatar
Raymond Knopp committed
60 61 62

#include "PHY/LTE_TRANSPORT/if4_tools.h"
#include "PHY/LTE_TRANSPORT/if5_tools.h"
63
#include "PHY/LTE_REFSIG/lte_refsig.h"
Raymond Knopp's avatar
Raymond Knopp committed
64

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

73 74 75 76 77
#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"
Raymond Knopp's avatar
Raymond Knopp committed
78

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

Cedric Roux's avatar
Cedric Roux committed
90 91 92 93
/* these variables have to be defined before including ENB_APP/enb_paramdef.h */
static int DEFBANDS[] = {7};
static int DEFENBS[] = {0};

94 95 96
#include "ENB_APP/enb_paramdef.h"
#include "common/config/config_userapi.h"

Raymond Knopp's avatar
Raymond Knopp committed
97
#ifndef OPENAIR2
98
  #include "UTIL/OTG/otg_extern.h"
Raymond Knopp's avatar
Raymond Knopp committed
99 100
#endif

101 102 103 104
#include "s1ap_eNB.h"
#include "SIMULATION/ETH_TRANSPORT/proto.h"


Raymond Knopp's avatar
Raymond Knopp committed
105 106 107

#include "T.h"

Wang Tsu-Han's avatar
Wang Tsu-Han committed
108
#include "pdcp.h"
Raymond Knopp's avatar
Raymond Knopp committed
109 110

extern volatile int                    oai_exit;
111
extern int emulate_rf;
112
extern int numerology;
113
extern clock_source_t clock_source;
114
extern uint8_t dlsch_ue_select_tbl_in_use;
frtabu's avatar
frtabu committed
115

Raymond Knopp's avatar
Raymond Knopp committed
116

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

122

Robert Schmidt's avatar
Robert Schmidt committed
123
void stop_RU(int nb_ru);
Raymond Knoppp's avatar
Raymond Knoppp committed
124
void do_ru_synch(RU_t *ru);
Raymond Knopp's avatar
Raymond Knopp committed
125

126
void reset_proc(RU_t *ru);
127
int connect_rau(RU_t *ru);
Raymond Knopp's avatar
Raymond Knopp committed
128

129 130
const char ru_states[6][9] = {"RU_IDLE","RU_CONFIG","RU_READY","RU_RUN","RU_ERROR","RU_SYNC"};

131
extern uint16_t sf_ahead;
132

133
#if defined(PRE_SCD_THREAD)
134
  void init_ru_vnf(void);
135 136 137
#endif


138 139 140
/*************************************************************/
/* Functions to attach and configure RRU                     */

141

Raymond Knopp's avatar
Raymond Knopp committed
142 143 144 145 146
/*************************************************************/
/* Southbound Fronthaul functions, RCC/RAU                   */

// southbound IF5 fronthaul for 16-bit OAI format
static inline void fh_if5_south_out(RU_t *ru) {
147
  if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );
148

149
  send_IF5(ru, ru->proc.timestamp_tx, ru->proc.subframe_tx, &ru->seqno, IF5_RRH_GW_DL);
Raymond Knopp's avatar
Raymond Knopp committed
150 151 152 153
}

// southbound IF4p5 fronthaul
static inline void fh_if4p5_south_out(RU_t *ru) {
154
  if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );
Raymond Knopp's avatar
Raymond Knopp committed
155
  LOG_D(PHY,"ENTERED fh_if4p5_south_out   Sending IF4p5 for frame %d subframe %d ru %d\n",ru->proc.frame_tx,ru->proc.subframe_tx,ru->idx);
156
  if (subframe_select(&ru->frame_parms,ru->proc.subframe_tx)!=SF_UL) {
157
    send_IF4p5(ru,ru->proc.frame_tx, ru->proc.subframe_tx, IF4p5_PDLFFT);
158
    ru->south_out_cnt++;
Raymond Knopp's avatar
Raymond Knopp committed
159
    LOG_D(PHY,"south_out_cnt %d\n",ru->south_out_cnt);
160
  }
magounak's avatar
magounak committed
161 162 163 164
/*if (ru == RC.ru[0] || ru == RC.ru[1]) {
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU+ru->idx, ru->proc.frame_tx );
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_RU+ru->idx, ru->proc.subframe_tx );
  }*/
magounak's avatar
magounak committed
165 166
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_IF4P5_SOUTH_OUT_RU+ru->idx,ru->proc.frame_tx);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_IF4P5_SOUTH_OUT_RU+ru->idx,ru->proc.subframe_tx);
magounak's avatar
magounak committed
167

Raymond Knopp's avatar
Raymond Knopp committed
168 169 170 171 172
}

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

173
// Synchronous if5 from south
Raymond Knopp's avatar
Raymond Knopp committed
174 175
void fh_if5_south_in(RU_t *ru,int *frame, int *subframe) {
  LTE_DL_FRAME_PARMS *fp = &ru->frame_parms;
176
  RU_proc_t *proc = &ru->proc;
177
  recv_IF5(ru, &proc->timestamp_rx, *subframe, IF5_RRH_GW_UL);
Raymond Knopp's avatar
Raymond Knopp committed
178 179
  proc->frame_rx    = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023;
  proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10;
180

Raymond Knopp's avatar
Raymond Knopp committed
181
  if (proc->first_rx == 0) {
182
    if (proc->subframe_rx != *subframe) {
183
      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);
Raymond Knopp's avatar
Raymond Knopp committed
184 185
      exit_fun("Exiting");
    }
186

Raymond Knopp's avatar
Raymond Knopp committed
187
    if (proc->frame_rx != *frame) {
188
      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);
Raymond Knopp's avatar
Raymond Knopp committed
189 190 191 192 193
      exit_fun("Exiting");
    }
  } else {
    proc->first_rx = 0;
    *frame = proc->frame_rx;
194 195
    *subframe = proc->subframe_rx;
  }
Raymond Knopp's avatar
Raymond Knopp committed
196

197
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
Raymond Knopp's avatar
Raymond Knopp committed
198 199
}

200
// Synchronous if4p5 from south
Raymond Knopp's avatar
Raymond Knopp committed
201 202
void fh_if4p5_south_in(RU_t *ru,int *frame,int *subframe) {
  LTE_DL_FRAME_PARMS *fp = &ru->frame_parms;
203 204
  RU_proc_t *proc = &ru->proc;
  int f,sf;
Raymond Knopp's avatar
Raymond Knopp committed
205 206
  uint16_t packet_type;
  uint32_t symbol_number=0;
207
  uint32_t symbol_mask_full;
208
  int pultick_received=0;
209

210

211 212 213 214
  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; 
215 216 217 218 219
  LOG_D(PHY,"fh_if4p5_south_in: RU %d, frame %d, subframe %d, ru %d, mask %x\n",ru->idx,*frame,*subframe,ru->idx,proc->symbol_mask[*subframe]);
  AssertFatal(proc->symbol_mask[*subframe]==0 || proc->symbol_mask[*subframe]==symbol_mask_full,"rx_fh_if4p5: proc->symbol_mask[%d] = %x\n",*subframe,proc->symbol_mask[*subframe]);
  if (proc->symbol_mask[*subframe]==0) { // this is normal case, if not true then we received a PULTICK before the previous subframe was finished 
     do {
       recv_IF4p5(ru, &f, &sf, &packet_type, &symbol_number);
220
	 LOG_D(PHY,"fh_if4p5_south_in: RU %d, frame %d, subframe %d, f %d, sf %d\n",ru->idx,*frame,*subframe,f,sf);
221 222 223 224 225
       if (oai_exit == 1 || ru->cmd== STOP_RU) break;
       if (packet_type == IF4p5_PULFFT) proc->symbol_mask[sf] = proc->symbol_mask[sf] | (1<<symbol_number);
       else if (packet_type == IF4p5_PULTICK) {           
         proc->symbol_mask[sf] = symbol_mask_full;
         pultick_received++;
226
/*
227 228
         if ((proc->first_rx==0) && (f!=*frame)) LOG_E(PHY,"rx_fh_if4p5: PULTICK received frame %d != expected %d (RU %d) \n",f,*frame, ru->idx);       
         else 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);       
229 230
         else break; */
         if (f==*frame || sf==*subframe) break;
231
       } else if (packet_type == IF4p5_PRACH) {
232
      // nothing in RU for RAU
233
       }
234 235
       LOG_D(PHY,"rx_fh_if4p5 for RU %d: subframe %d, sf %d, symbol mask %x\n",ru->idx,*subframe,sf,proc->symbol_mask[sf]);
     } while(proc->symbol_mask[sf] != symbol_mask_full);    
236 237 238 239 240
  }
  else {
   f = *frame;
   sf = *subframe;
  }
magounak's avatar
magounak committed
241
  //calculate timestamp_rx, timestamp_tx based on frame and subframe
242 243
  proc->subframe_rx  = sf;
  proc->frame_rx     = f;
244
  proc->timestamp_rx = ((proc->frame_rx * 10)  + proc->subframe_rx ) * fp->samples_per_tti ;
cdxu0312's avatar
cdxu0312 committed
245 246 247 248 249
  if (get_nprocs()<=4) {
     proc->subframe_tx  = (sf+sf_ahead)%10;
     proc->frame_tx     = (sf>(9-sf_ahead)) ? (f+1)&1023 : f;
  }

250
  LOG_D(PHY,"Setting proc for (%d,%d)\n",sf,f);
251

Raymond Knopp's avatar
Raymond Knopp committed
252
  if (proc->first_rx == 0) {
magounak's avatar
magounak committed
253
   if (proc->subframe_rx != *subframe){
254 255 256
      LOG_E(PHY,"Received Timestamp (IF4p5) doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d, symbol_mask %x)\n",proc->subframe_rx,*subframe,proc->symbol_mask[*subframe]);
      *subframe=sf; 
      //exit_fun("Exiting");
Raymond Knopp's avatar
Raymond Knopp committed
257
    }
258
    if (ru->cmd != WAIT_RESYNCH && proc->frame_rx != *frame) {
259 260
      LOG_E(PHY,"Received Timestamp (IF4p5) doesn't correspond to the time we think it is (proc->frame_rx %d frame %d,symbol_mask %x\n",proc->frame_rx,*frame,proc->symbol_mask[*subframe]);
      //exit_fun("Exiting");
Raymond Knopp's avatar
Raymond Knopp committed
261
    }
262 263 264
    else if (ru->cmd == WAIT_RESYNCH && proc->frame_rx != *frame){
       ru->cmd=EMPTY;
       *frame=proc->frame_rx; 
Raymond Knopp's avatar
Raymond Knopp committed
265 266 267 268
    }
  } else {
    proc->first_rx = 0;
    *frame = proc->frame_rx;
269
    *subframe = proc->subframe_rx;
Raymond Knopp's avatar
Raymond Knopp committed
270
  }
271

magounak's avatar
magounak committed
272
  /*if (ru == RC.ru[0] || ru == RC.ru[1]) {
273 274
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_RU+ru->idx, f );
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_RU+ru->idx, sf );
magounak's avatar
magounak committed
275 276 277
    
  }*/

magounak's avatar
magounak committed
278 279
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_IF4P5_SOUTH_IN_RU+ru->idx,f);
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_IF4P5_SOUTH_IN_RU+ru->idx,sf);
280

281
  proc->symbol_mask[sf] = 0;
Raymond Knopp's avatar
Raymond Knopp committed
282
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
283 284
  LOG_D(PHY,"RU %d: fh_if4p5_south_in returning ...\n",ru->idx);
  //  usleep(100);
Raymond Knopp's avatar
Raymond Knopp committed
285 286 287 288 289 290
}

// 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
291
  RU_proc_t *proc=&ru->proc;
Raymond Knopp's avatar
Raymond Knopp committed
292 293 294 295 296 297 298 299 300 301

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

// 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;
302
  RU_proc_t *proc       = &ru->proc;
Raymond Knopp's avatar
Raymond Knopp committed
303
  uint16_t packet_type;
Raymond Knopp's avatar
Raymond Knopp committed
304
  uint32_t symbol_number,symbol_mask,prach_rx;
305
  uint32_t got_prach_info=0;
Raymond Knopp's avatar
Raymond Knopp committed
306
  symbol_number = 0;
307 308
  symbol_mask   = (1<<fp->symbols_per_tti)-1;
  prach_rx      = 0;
Raymond Knopp's avatar
Raymond Knopp committed
309 310 311

  do {   // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!!
    recv_IF4p5(ru, &proc->frame_rx, &proc->subframe_rx, &packet_type, &symbol_number);
312

313
    if (ru->cmd == STOP_RU) break;
314 315 316 317 318
    // 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;
    }
319

Raymond Knopp's avatar
Raymond Knopp committed
320 321 322 323
    if (proc->first_rx != 0) {
      *frame = proc->frame_rx;
      *subframe = proc->subframe_rx;
      proc->first_rx = 0;
324
    } else {
Raymond Knopp's avatar
Raymond Knopp committed
325
      if (proc->frame_rx != *frame) {
326 327
        LOG_E(PHY,"frame_rx %d is not what we expect %d\n",proc->frame_rx,*frame);
        exit_fun("Exiting");
Raymond Knopp's avatar
Raymond Knopp committed
328
      }
329

Raymond Knopp's avatar
Raymond Knopp committed
330
      if (proc->subframe_rx != *subframe) {
331 332
        LOG_E(PHY,"subframe_rx %d is not what we expect %d\n",proc->subframe_rx,*subframe);
        exit_fun("Exiting");
Raymond Knopp's avatar
Raymond Knopp committed
333 334
      }
    }
335

336 337
    if      (packet_type == IF4p5_PULFFT)       symbol_mask &= (~(1<<symbol_number));
    else if (packet_type == IF4p5_PRACH)        prach_rx    &= (~0x1);
338

339
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
340 341 342 343
    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);
344

345
#endif
346 347
  } while( (symbol_mask > 0) || (prach_rx >0));   // haven't received all PUSCH symbols and PRACH information
}
Raymond Knopp's avatar
Raymond Knopp committed
348 349 350 351 352 353 354





/*************************************************************/
/* Input Fronthaul from North RRU                            */
355 356

// RRU IF4p5 TX fronthaul receiver. Assumes an if_device on input and if or rf device on output
Raymond Knopp's avatar
Raymond Knopp committed
357
// receives one subframe's worth of IF4p5 OFDM symbols and OFDM modulates
358
void fh_if4p5_north_in(RU_t *ru,int *frame,int *subframe) {
Raymond Knopp's avatar
Raymond Knopp committed
359 360 361
  uint32_t symbol_number=0;
  uint32_t symbol_mask, symbol_mask_full;
  uint16_t packet_type;
362
  /// **** incoming IF4p5 from remote RCC/RAU **** ///
Raymond Knopp's avatar
Raymond Knopp committed
363 364 365
  symbol_number = 0;
  symbol_mask = 0;
  symbol_mask_full = (1<<ru->frame_parms.symbols_per_tti)-1;
magounak's avatar
magounak committed
366
  LOG_D(PHY,"fh_if4p5_north_in: frame %d, subframe %d\n",*frame,*subframe);
367

Raymond Knopp's avatar
Raymond Knopp committed
368
  do { 
369
    recv_IF4p5(ru, frame, subframe, &packet_type, &symbol_number);
Raymond Knopp's avatar
Raymond Knopp committed
370 371
    symbol_mask = symbol_mask | (1<<symbol_number);
  } while (symbol_mask != symbol_mask_full); 
magounak's avatar
magounak committed
372
  
373
  ru->north_in_cnt++;
374 375
  // dump VCD output for first RU in list
  if (ru == RC.ru[0]) {
376 377
    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 );
Raymond Knopp's avatar
Raymond Knopp committed
378 379 380 381 382
  }
}

void fh_if5_north_asynch_in(RU_t *ru,int *frame,int *subframe) {
  LTE_DL_FRAME_PARMS *fp = &ru->frame_parms;
383
  RU_proc_t *proc        = &ru->proc;
Raymond Knopp's avatar
Raymond Knopp committed
384 385
  int subframe_tx,frame_tx;
  openair0_timestamp timestamp_tx;
386 387
  recv_IF5(ru, &timestamp_tx, *subframe, IF5_RRH_GW_DL);
  //      printf("Received subframe %d (TS %llu) from RCC\n",subframe_tx,timestamp_tx);
Raymond Knopp's avatar
Raymond Knopp committed
388 389 390
  subframe_tx = (timestamp_tx/fp->samples_per_tti)%10;
  frame_tx    = (timestamp_tx/(fp->samples_per_tti*10))&1023;

Raymond Knopp's avatar
Raymond Knopp committed
391 392 393
  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 );
  
Raymond Knopp's avatar
Raymond Knopp committed
394 395 396 397
  if (proc->first_tx != 0) {
    *subframe = subframe_tx;
    *frame    = frame_tx;
    proc->first_tx = 0;
398
  } else {
399 400
    AssertFatal(subframe_tx == *subframe,
                "subframe_tx %d is not what we expect %d\n",subframe_tx,*subframe);
401
    AssertFatal(frame_tx == *frame,
402
                "frame_tx %d is not what we expect %d\n",frame_tx,*frame);
Raymond Knopp's avatar
Raymond Knopp committed
403
  }
404
  ru->north_in_cnt++;
Raymond Knopp's avatar
Raymond Knopp committed
405 406 407 408
}

void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *subframe) {
  LTE_DL_FRAME_PARMS *fp = &ru->frame_parms;
409
  RU_proc_t *proc        = &ru->proc;
Raymond Knopp's avatar
Raymond Knopp committed
410 411 412
  uint16_t packet_type;
  uint32_t symbol_number,symbol_mask,symbol_mask_full;
  int subframe_tx,frame_tx;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
413
  int ret;
Raymond Knopp's avatar
Raymond Knopp committed
414 415 416

  symbol_number = 0;
  symbol_mask = 0;
417
  symbol_mask_full = ((subframe_select(fp,*subframe) == SF_S) ? (1<<fp->dl_symbols_in_S_subframe) : (1<<fp->symbols_per_tti))-1;
magounak's avatar
magounak committed
418
  LOG_D(PHY,"fh_if4p5_north_asynch_in: RU %d, frame %d, subframe %d\n",ru->idx,*frame,*subframe);
Raymond Knopp's avatar
Raymond Knopp committed
419 420
  do {   
    recv_IF4p5(ru, &frame_tx, &subframe_tx, &packet_type, &symbol_number);
Raymond Knopp's avatar
Raymond Knopp committed
421
    LOG_D(PHY,"income frame.subframe %d.%d, our frame.subframe.symbol_number %d.%d.%d (symbol mask %x)\n",frame_tx,subframe_tx,*frame,*subframe,symbol_number,symbol_mask);
422
    if (ru->cmd == STOP_RU){
Raymond Knopp's avatar
Raymond Knopp committed
423
      LOG_E(PHY,"Got STOP_RU\n");
Wang Tsu-Han's avatar
Wang Tsu-Han committed
424
      AssertFatal((ret=pthread_mutex_lock(&proc->mutex_ru))==0,"mutex_lock returns %d\n",ret);
Raymond Knopp's avatar
Raymond Knopp committed
425
      proc->instance_cnt_ru = -1;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
426
      AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_ru))==0,"mutex_unlock returns %d\n",ret);
427
      ru->cmd=STOP_RU;
Raymond Knopp's avatar
Raymond Knopp committed
428
      return;
429
    } 
430
    if ((subframe_select(fp,subframe_tx) == SF_DL) && (symbol_number == 0)) start_meas(&ru->rx_fhaul);
431

432
    LOG_D(PHY,"subframe %d (%d): frame %d, subframe %d, symbol %d\n",
Raymond Knopp's avatar
Raymond Knopp committed
433
	  *subframe,subframe_select(fp,*subframe),frame_tx,subframe_tx,symbol_number);
434

Raymond Knopp's avatar
Raymond Knopp committed
435 436 437 438
    if (proc->first_tx != 0) {
      *frame    = frame_tx;
      *subframe = subframe_tx;
      proc->first_tx = 0;
439
      symbol_mask_full = ((subframe_select(fp,*subframe) == SF_S) ? (1<<fp->dl_symbols_in_S_subframe) : (1<<fp->symbols_per_tti))-1;
440
    } else {
441
     /* AssertFatal(frame_tx == *frame,
442
                  "frame_tx %d is not what we expect %d\n",frame_tx,*frame);
443
      AssertFatal(subframe_tx == *subframe,
444
		  "In frame_tx %d : subframe_tx %d is not what we expect %d\n",frame_tx,subframe_tx,*subframe);
445 446 447
     */
      *frame    = frame_tx;
      *subframe = subframe_tx;
Raymond Knopp's avatar
Raymond Knopp committed
448
    }
449

Raymond Knopp's avatar
Raymond Knopp committed
450 451 452
    if (packet_type == IF4p5_PDLFFT) {
      symbol_mask = symbol_mask | (1<<symbol_number);
    }
453
    else AssertFatal(1==0,"Illegal IF4p5 packet type (should only be IF4p5_PDLFFT got %d\n",packet_type);
Raymond Knopp's avatar
Raymond Knopp committed
454
  } while (symbol_mask != symbol_mask_full);    
455

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

458 459
  ru->north_in_cnt++;

460 461 462 463
  proc->subframe_tx  = subframe_tx;
  proc->frame_tx     = frame_tx;

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

465
  proc->timestamp_tx = ((((uint64_t)frame_tx + (uint64_t)proc->frame_tx_unwrap) * 10) + (uint64_t)subframe_tx) * (uint64_t)fp->samples_per_tti;
466
  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);
467
  // dump VCD output for first RU in list
468
  if (ru == RC.ru[0]) {
magounak's avatar
magounak committed
469
    /*VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame_tx );
470
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_RU, subframe_tx );
magounak's avatar
magounak committed
471 472 473
    */
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_IF4P5_NORTH_ASYNCH_IN,frame_tx);
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_IF4P5_NORTH_ASYNCH_IN,subframe_tx);
474
  }
475

Raymond Knopp's avatar
Raymond Knopp committed
476

477
  if (ru->feptx_ofdm) ru->feptx_ofdm(ru);
478

479
  if (ru->fh_south_out) ru->fh_south_out(ru);
480
}
Raymond Knopp's avatar
Raymond Knopp committed
481

482 483 484
void fh_if5_north_out(RU_t *ru) {
  RU_proc_t *proc=&ru->proc;
  uint8_t seqno=0;
485 486
  /// **** send_IF5 of rxdata to BBU **** ///
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 );
487
  send_IF5(ru, proc->timestamp_rx, proc->subframe_rx, &seqno, IF5_RRH_GW_UL);
488
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 );
489 490 491 492 493 494 495
}

// 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;
magounak's avatar
magounak committed
496 497 498 499 500
  if (ru->idx==0){
 	 VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_IF4P5_NORTH_OUT, proc->subframe_rx );
         VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_IF4P5_NORTH_OUT, proc->frame_rx );
  }
  LOG_D(PHY,"fh_if4p5_north_out: Sending IF4p5_PULFFT SFN.SF %d.%d\n",proc->frame_rx,proc->subframe_rx);
501 502
  if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) {
    /// **** in TDD during DL send_IF4 of ULTICK to RCC **** ///
503
    send_IF4p5(ru, proc->frame_rx, proc->subframe_rx, IF4p5_PULTICK);
504
    ru->north_out_cnt++;
505 506 507
    return;
  }

508 509
  start_meas(&ru->tx_fhaul);
  send_IF4p5(ru, proc->frame_rx, proc->subframe_rx, IF4p5_PULFFT);
510
  ru->north_out_cnt++;
511
  stop_meas(&ru->tx_fhaul);
512
}
513

Wang Tsu-Han's avatar
Wang Tsu-Han committed
514 515
/* add fail safe for late command */
typedef enum {
516 517 518 519 520
  STATE_BURST_NORMAL = 0,
  STATE_BURST_TERMINATE = 1,
  STATE_BURST_STOP_1 = 2,
  STATE_BURST_STOP_2 = 3,
  STATE_BURST_RESTART = 4,
Wang Tsu-Han's avatar
Wang Tsu-Han committed
521 522 523 524 525 526
} late_control_e;

volatile late_control_e late_control=STATE_BURST_NORMAL;

/* add fail safe for late command end */

527
static void *emulatedRF_thread(void *param) {
528 529 530
  RU_proc_t *proc = (RU_proc_t *) param;
  int microsec = 500; // length of time to sleep, in miliseconds
  struct timespec req = {0};
531
  int numerology = get_softmodem_params()->numerology;
532
  req.tv_sec = 0;
Eurecom's avatar
Eurecom committed
533
  req.tv_nsec = (numerology>0)? ((microsec * 1000L)/numerology):(microsec * 1000L)*2;
534
  cpu_set_t cpuset;
535
  CPU_ZERO(&cpuset);
536 537 538
  CPU_SET(1,&cpuset);
  pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
  int policy;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
539 540
  int ret;

541 542 543
  struct sched_param sparam;
  memset(&sparam, 0, sizeof(sparam));
  sparam.sched_priority = sched_get_priority_max(SCHED_FIFO);
544
  policy = SCHED_FIFO ;
545
  pthread_setschedparam(pthread_self(), policy, &sparam);
546
  wait_sync("emulatedRF_thread");
547 548

  while(!oai_exit) {
549
    nanosleep(&req, (struct timespec *)NULL);
550 551

    if(proc->emulate_rf_busy ) {
552 553
      LOG_E(PHY,"rf being delayed in emulated RF\n");
    }
554

555
    proc->emulate_rf_busy = 1;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
556
    AssertFatal((ret=pthread_mutex_lock(&proc->mutex_emulateRF))==0,"mutex_lock returns %d\n",ret);
557 558
    ++proc->instance_cnt_emulateRF;
    pthread_cond_signal(&proc->cond_emulateRF);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
559
    AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_emulateRF))==0,"mutex_unlock returns %d\n",ret);
560
  }
561

562 563 564
  return 0;
}

Raymond Knopp's avatar
Raymond Knopp committed
565
void rx_rf(RU_t *ru,int *frame,int *subframe) {
566
  RU_proc_t *proc = &ru->proc;
Raymond Knopp's avatar
Raymond Knopp committed
567
  LTE_DL_FRAME_PARMS *fp = &ru->frame_parms;
568
  void *rxp[ru->nb_rx];
569
  unsigned int rxs;
Raymond Knopp's avatar
Raymond Knopp committed
570
  int i;
571

572

573 574
  int resynch=0;
  
575

Wang Tsu-Han's avatar
Wang Tsu-Han committed
576
  openair0_timestamp ts=0,old_ts=0;
577
  for (i=0; i<ru->nb_rx; i++)
578
    rxp[i] = (void *)&ru->common.rxdata[i][*subframe*fp->samples_per_tti];
579

Raymond Knopp's avatar
Raymond Knopp committed
580
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 );
581
  old_ts = proc->timestamp_rx;
582 583

  if(get_softmodem_params()->emulate_rf) {
584 585 586
    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;
587
  } else {
588
    rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
589 590 591 592
                                     &ts,
                                     rxp,
                                     fp->samples_per_tti,
                                     ru->nb_rx);
593
  }
594

Raymond Knopp's avatar
Raymond Knopp committed
595
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
596

597
  ru->south_in_cnt++;
598
  LOG_D(PHY,"south_in_cnt %d\n",ru->south_in_cnt);
599

600
  if (ru->cmd==RU_FRAME_RESYNCH) {
601 602 603
    LOG_I(PHY,"Applying frame resynch %d => %d\n",*frame,ru->cmdval);
    if (proc->frame_rx>ru->cmdval) ru->ts_offset += (proc->frame_rx - ru->cmdval)*fp->samples_per_tti*10;
    else ru->ts_offset -= (-proc->frame_rx + ru->cmdval)*fp->samples_per_tti*10;
604 605
    *frame = ru->cmdval;
    ru->cmd=EMPTY;
606
    resynch=1;
607
  }
Raymond Knopp's avatar
Raymond Knopp committed
608
 
609 610
  proc->timestamp_rx = ts-ru->ts_offset;

611 612 613
  //  AssertFatal(rxs == fp->samples_per_tti,
  //        "rx_rf: Asked for %d samples, got %d from SDR\n",fp->samples_per_tti,rxs);
  if(rxs != fp->samples_per_tti) {
614
    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
615 616
    late_control=STATE_BURST_TERMINATE;
  }
617 618

  if (proc->first_rx == 1) {
619
    ru->ts_offset = proc->timestamp_rx;
620
    proc->timestamp_rx = 0;
621 622 623 624 625
  } 
  else if (resynch==0 && (proc->timestamp_rx - old_ts != fp->samples_per_tti)) {
    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);
    ru->ts_offset += (proc->timestamp_rx - old_ts - fp->samples_per_tti);
    proc->timestamp_rx = ts-ru->ts_offset;
626
  }
627

628

629 630
  proc->frame_rx     = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023;
  proc->subframe_rx  = (proc->timestamp_rx / fp->samples_per_tti)%10;
Raymond Knopp's avatar
Raymond Knopp committed
631 632
  // synchronize first reception to frame 0 subframe 0

633

Raymond Knopp's avatar
Raymond Knopp committed
634
  if (ru->fh_north_asynch_in == NULL) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
635
#ifdef PHY_TX_THREAD
636 637 638
    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;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
639
#endif
640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658
    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);
    
    LOG_D(PHY,"south_in/rx_rf: 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);
    // 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 );
      if (ru->fh_north_asynch_in == NULL) {
	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 );
      }
Raymond Knopp's avatar
Raymond Knopp committed
659
    }
660
  }
661

Raymond Knopp's avatar
Raymond Knopp committed
662
  if (proc->first_rx == 0) {
663
    if (proc->subframe_rx != *subframe) {
664
      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);
Raymond Knopp's avatar
Raymond Knopp committed
665 666
      exit_fun("Exiting");
    }
667

Raymond Knopp's avatar
Raymond Knopp committed
668
    if (proc->frame_rx != *frame) {
669
      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);
Raymond Knopp's avatar
Raymond Knopp committed
670 671 672 673 674
      exit_fun("Exiting");
    }
  } else {
    proc->first_rx = 0;
    *frame = proc->frame_rx;
675
    *subframe = proc->subframe_rx;
Raymond Knopp's avatar
Raymond Knopp committed
676
  }
677

Raymond Knopp's avatar
Raymond Knopp committed
678
  //printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",ru->timestamp_rx,proc->frame_rx,frame,proc->subframe_rx,subframe);
679
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
680 681

  if (rxs != fp->samples_per_tti) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
682 683
#if defined(USRP_REC_PLAY)
    exit_fun("Exiting IQ record/playback");
684
#else
685
    //exit_fun( "problem receiving samples" );
Cedric Roux's avatar
Cedric Roux committed
686
    LOG_E(PHY, "problem receiving samples");
687
#endif
688
  }
Raymond Knopp's avatar
Raymond Knopp committed
689 690 691
}


692 693 694
void tx_rf(RU_t *ru) {
  RU_proc_t *proc = &ru->proc;
  LTE_DL_FRAME_PARMS *fp = &ru->frame_parms;
695
  void *txp[ru->nb_tx];
696 697
  unsigned int txs;
  int i;
Cedric Roux's avatar
Cedric Roux committed
698 699
  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));
700 701
  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);
702
  int sf_extension = 0;
magounak's avatar
magounak committed
703
  
704

705 706 707
  if ((SF_type == SF_DL) ||
      (SF_type == SF_S)) {
    int siglen=fp->samples_per_tti,flags=1;
708

709
    if (SF_type == SF_S) {
710 711
      int txsymb = fp->dl_symbols_in_S_subframe+(ru->is_slave==0 ? 1 : 0);
      AssertFatal(txsymb>0,"illegal txsymb %d\n",txsymb);
712 713 714 715 716 717 718
      /* end_of_burst_delay is used to stop TX only "after a while".
       * If we stop right after effective signal, with USRP B210 and
       * B200mini, we observe a high EVM on the S subframe (on the
       * PSS).
       * A value of 400 (for 30.72MHz) solves this issue. This is
       * the default.
       */
719
      siglen = (fp->ofdm_symbol_size + fp->nb_prefix_samples0)
720
               + (txsymb - 1) * (fp->ofdm_symbol_size + fp->nb_prefix_samples)
721
               + ru->end_of_burst_delay;
722 723
      flags=3; // end of burst
    }
724

725 726 727
    if (fp->frame_type == TDD &&
        SF_type == SF_DL &&
        prevSF_type == SF_UL) {
728
      flags = 2; // start of burst
729
      sf_extension = ru->sf_extension;
730
    }
731

Wang Tsu-Han's avatar
Wang Tsu-Han committed
732 733
#if defined(__x86_64) || defined(__i386__)
#ifdef __AVX2__
734
    sf_extension = (sf_extension)&0xfffffff8;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
735
#else
736
    sf_extension = (sf_extension)&0xfffffffc;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
737 738
#endif
#elif defined(__arm__)
739
    sf_extension = (sf_extension)&0xfffffffc;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
740
#endif
741

742
    for (i=0; i<ru->nb_tx; i++)
743
      txp[i] = (void *)&ru->common.txdata[i][(proc->subframe_tx*fp->samples_per_tti)-sf_extension];
744

Wang Tsu-Han's avatar
Wang Tsu-Han committed
745
    /* add fail safe for late command */
746
    if(late_control!=STATE_BURST_NORMAL) { //stop burst
Wang Tsu-Han's avatar
Wang Tsu-Han committed
747
      switch (late_control) {
748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772
        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;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
773 774 775
      }
    }

776
    /* add fail safe for late command end */
Raymond Knopp's avatar
Raymond Knopp committed
777 778
    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 );
779 780 781 782
    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,
783
				      proc->timestamp_tx+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension,
784
				      txp,
785
				      siglen+sf_extension,
786 787
				      ru->nb_tx,
				      flags);
788
    ru->south_out_cnt++;
Raymond Knopp's avatar
Raymond Knopp committed
789
    LOG_D(PHY,"south_out_cnt %d\n",ru->south_out_cnt);
790
    int se = dB_fixed(signal_energy(txp[0],siglen+sf_extension));
magounak's avatar
magounak committed
791

792 793
    if (SF_type == SF_S) LOG_D(PHY,"[TXPATH] RU %d tx_rf (en %d,len %d), writing to TS %llu, frame %d, unwrapped_frame %d, subframe %d\n",ru->idx,se,siglen+sf_extension,
	  (long long unsigned int)proc->timestamp_tx,proc->frame_tx,proc->frame_tx_unwrap,proc->subframe_tx);
794
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
795 796 797

    //    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 */
Wang Tsu-Han's avatar
Wang Tsu-Han committed
798 799 800
      late_control=STATE_BURST_TERMINATE;
      LOG_E(PHY,"TX : Timeout (sent %d/%d) state =%d\n",txs, siglen,late_control);
    }
801
  }
802 803 804
}


Raymond Knopp's avatar
Raymond Knopp committed
805 806 807
/*!
 * \brief The Asynchronous RX/TX FH thread of RAU/RCC/eNB/RRU.
 * This handles the RX FH for an asynchronous RRU/UE
808
 * \param param is a \ref L1_proc_t structure which contains the info what to process.
Raymond Knopp's avatar
Raymond Knopp committed
809 810
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
811
void *ru_thread_asynch_rxtx( void *param ) {
Raymond Knopp's avatar
Raymond Knopp committed
812
  static int ru_thread_asynch_rxtx_status;
813
  RU_t *ru         = (RU_t *)param;
814
  RU_proc_t *proc  = &ru->proc;
815
  int subframe=0, frame=0;
816
  thread_top_init("ru_thread_asynch_rxtx",1,870000,1000000,1000000);
Raymond Knopp's avatar
Raymond Knopp committed
817
  // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe
818
  wait_sync("ru_thread_asynch_rxtx");
Raymond Knopp's avatar
Raymond Knopp committed
819
  // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe
Raymond Knopp's avatar
Raymond Knopp committed
820
  LOG_I(PHY, "waiting for devices (ru_thread_asynch_rxtx)\n");
Raymond Knopp's avatar
Raymond Knopp committed
821 822 823

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

Raymond Knopp's avatar
Raymond Knopp committed
824
  LOG_I(PHY, "devices ok (ru_thread_asynch_rxtx)\n");
Raymond Knopp's avatar
Raymond Knopp committed
825

826 827
  while (!oai_exit) {
    if (oai_exit) break;
Raymond Knopp's avatar
Raymond Knopp committed
828

829
    if (ru->state != RU_RUN) {
Raymond Knopp's avatar
Raymond Knopp committed
830
      subframe=0;
831 832 833 834 835 836 837 838 839 840
      frame=0;
      usleep(1000);
    }
    else {
      if (subframe==9) { 
         subframe=0;
         frame++;
         frame&=1023;
       } else {
         subframe++;
841 842 843 844 845 846 847 848
      }      
      LOG_D(PHY,"ru_thread_asynch_rxtx: Waiting on incoming fronthaul\n");
      // asynchronous receive from north (RRU IF4/IF5)
      if (ru->fh_north_asynch_in) {
	if (subframe_select(&ru->frame_parms,subframe)!=SF_UL)
	  ru->fh_north_asynch_in(ru,&frame,&subframe);
      }
      else AssertFatal(1==0,"Unknown function in ru_thread_asynch_rxtx\n");
849
    }
Raymond Knopp's avatar
Raymond Knopp committed
850 851 852 853 854 855 856 857
  }
  ru_thread_asynch_rxtx_status=0;
  return(&ru_thread_asynch_rxtx_status);
}




858
void wakeup_slaves(RU_proc_t *proc) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
859
  int i,ret;
Raymond Knopp's avatar
Raymond Knopp committed
860
  struct timespec wait;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
861
  int time_ns = 5000000L;
862 863

  for (i=0; i<proc->num_slaves; i++) {
864
    RU_proc_t *slave_proc = proc->slave_proc[i];
865

Raymond Knopp's avatar
Raymond Knopp committed
866 867
    // wake up slave FH thread
    // lock the FH mutex and make sure the thread is ready
Wang Tsu-Han's avatar
Wang Tsu-Han committed
868 869
    clock_gettime(CLOCK_REALTIME,&wait);
    wait.tv_nsec += time_ns;
870 871 872 873
    if(wait.tv_nsec >= 1000*1000*1000)
    {
      wait.tv_nsec -= 1000*1000*1000;
      wait.tv_sec  += 1;
Raymond Knopp's avatar
Raymond Knopp committed
874
    }
875
    AssertFatal((ret=pthread_mutex_timedlock(&slave_proc->mutex_FH,&wait))==0,"ERROR pthread_mutex_lock for RU %d slave %d (IC %d)\n",proc->ru->idx,slave_proc->ru->idx,slave_proc->instance_cnt_FH);
876

Raymond Knopp's avatar
Raymond Knopp committed
877 878 879 880
    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;
881
    slave_proc->timestamp_tx = proc->timestamp_tx;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
882
    AssertFatal((ret=pthread_mutex_unlock( &slave_proc->mutex_FH ))==0,"mutex_unlock returns %d\n",ret);
883

Raymond Knopp's avatar
Raymond Knopp committed
884 885 886
    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) {
887
	LOG_E( PHY, "ERROR pthread_cond_signal for RU %d, slave RU %d\n",proc->ru->idx,slave_proc->ru->idx);
Raymond Knopp's avatar
Raymond Knopp committed
888 889
	exit_fun( "ERROR pthread_cond_signal" );
	break;
Raymond Knopp's avatar
Raymond Knopp committed
890 891
      }
    } else {
892
      LOG_W( PHY,"[RU] Frame %d, slave %d thread busy!! (cnt_FH %i)\n",slave_proc->frame_rx,slave_proc->ru->idx, cnt_slave);
Raymond Knopp's avatar
Raymond Knopp committed
893 894
      exit_fun( "FH thread busy" );
      break;
895
    }
Raymond Knopp's avatar
Raymond Knopp committed
896 897 898 899 900
  }
}

/*!
 * \brief The prach receive thread of RU.
901
 * \param param is a \ref RU_proc_t structure which contains the info what to process.
Raymond Knopp's avatar
Raymond Knopp committed
902 903
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
904
void *ru_thread_prach( void *param ) {
Raymond Knopp's avatar
Raymond Knopp committed
905
  static int ru_thread_prach_status;
906 907
  RU_t *ru        = (RU_t *)param;
  RU_proc_t *proc = (RU_proc_t *)&ru->proc;
Raymond Knopp's avatar
Raymond Knopp committed
908
  // set default return value
909
  ru_thread_prach_status = 0;
910
  thread_top_init("ru_thread_prach",1,500000,1000000,20000000);
911
  //wait_sync("ru_thread_prach");
Raymond Knopp's avatar
Raymond Knopp committed
912

913
  while (RC.ru_mask>0 && ru->function!=eNodeB_3GPP) {
914
    usleep(1e6);
915
    LOG_D(PHY,"%s() RACH waiting for RU to be configured\n", __FUNCTION__);
916
  }
917

918
  LOG_I(PHY,"%s() RU configured - RACH processing thread running\n", __FUNCTION__);
Raymond Knopp's avatar
Raymond Knopp committed
919 920

  while (!oai_exit) {
921
    if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break;
922

923
    if (oai_exit) break;
924 925 926 927

    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 1 );

    if (ru->eNB_list[0]) {
928
      prach_procedures(
929
        ru->eNB_list[0]
930
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
931
        ,0
932
#endif
933 934 935 936 937 938 939
      );
    } else {
      rx_prach(NULL,
               ru,
               NULL,
               NULL,
               NULL,
940
	       NULL,
941 942
               proc->frame_prach,
               0
943
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
944
               ,0
945
#endif
946 947 948 949 950
              );
    }

    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 );

951
    if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break;
Raymond Knopp's avatar
Raymond Knopp committed
952 953
  }

954 955 956 957 958
  LOG_I(PHY, "Exiting RU thread PRACH\n");
  ru_thread_prach_status = 0;
  return &ru_thread_prach_status;
}

959
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
960
void *ru_thread_prach_br( void *param ) {
961
  static int ru_thread_prach_status;
962 963
  RU_t *ru        = (RU_t *)param;
  RU_proc_t *proc = (RU_proc_t *)&ru->proc;
964 965
  // set default return value
  ru_thread_prach_status = 0;
966
  thread_top_init("ru_thread_prach_br",1,500000,1000000,20000000);
967
  //wait_sync("ru_thread_prach_br");
968 969 970

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

972
    if (oai_exit) break;
973

974
    rx_prach(NULL,
975 976
             ru,
             NULL,
977 978
             NULL,
             NULL,
979
	     NULL,
980 981
             proc->frame_prach_br,
             0,
982 983
             1);

984 985 986 987
    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");
988 989
  ru_thread_prach_status = 0;
  return &ru_thread_prach_status;
Raymond Knopp's avatar
Raymond Knopp committed
990
}
991
#endif
Raymond Knopp's avatar
Raymond Knopp committed
992

993
int wakeup_synch(RU_t *ru) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
994
  int ret;
995
  struct timespec wait;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
996
  int time_ns = 5000000L;
Raymond Knopp's avatar
Raymond Knopp committed
997

998
  // wake up synch thread
Raymond Knopp's avatar
Raymond Knopp committed
999
  // lock the synch mutex and make sure the thread is readif (pthread_mutex_timedlock(&ru->proc.mutex_synch,&wait) != 0) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1000 1001
  clock_gettime(CLOCK_REALTIME,&wait);
  wait.tv_nsec += time_ns;
1002 1003 1004 1005
  if(wait.tv_nsec >= 1000*1000*1000)
  {
    wait.tv_nsec -= 1000*1000*1000;
    wait.tv_sec  += 1;
1006
  }
1007
  AssertFatal((ret=pthread_mutex_timedlock(&ru->proc.mutex_synch,&wait)) == 0,"[RU] ERROR pthread_mutex_lock for RU synch thread (IC %d)\n", ru->proc.instance_cnt_synch );
1008

1009
  ++ru->proc.instance_cnt_synch;
1010

1011 1012 1013 1014 1015 1016 1017
  // 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);
  }

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1018
  AssertFatal((ret=pthread_mutex_unlock( &ru->proc.mutex_synch ))==0,"mutex_unlock returns %d\n",ret);
1019 1020 1021 1022 1023 1024 1025
  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;
Raymond Knopp's avatar
Raymond Knopp committed
1026 1027
  void *rxp[2],*rxp2[2];
  int32_t dummy_rx[ru->nb_rx][fp->samples_per_tti] __attribute__((aligned(32)));
1028 1029
  int rxs;
  int ic;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1030
  int ret;
Raymond Knopp's avatar
Raymond Knopp committed
1031 1032

  // initialize the synchronization buffer to the common_vars.rxdata
1033
  for (int i=0; i<ru->nb_rx; i++)
1034
    rxp[i] = &ru->common.rxdata[i][0];
Raymond Knopp's avatar
Raymond Knopp committed
1035 1036

  double temp_freq1 = ru->rfdevice.openair0_cfg->rx_freq[0];
1037 1038

  for (i=0; i<4; i++) {
Raymond Knopp's avatar
Raymond Knopp committed
1039 1040 1041
    ru->rfdevice.openair0_cfg->rx_freq[i] = ru->rfdevice.openair0_cfg->tx_freq[i];
    ru->rfdevice.openair0_cfg->tx_freq[i] = temp_freq1;
  }
1042

Raymond Knopp's avatar
Raymond Knopp committed
1043
  ru->rfdevice.trx_set_freq_func(&ru->rfdevice,ru->rfdevice.openair0_cfg,0);
1044

Raymond Knopp's avatar
Raymond Knopp committed
1045 1046 1047
  while ((ru->in_synch ==0)&&(!oai_exit)) {
    // read in frame
    rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
1048 1049 1050 1051 1052
                                     &(proc->timestamp_rx),
                                     rxp,
                                     fp->samples_per_tti*10,
                                     ru->nb_rx);

1053
    if (rxs != fp->samples_per_tti*10) LOG_E(PHY,"requested %d samples, got %d\n",fp->samples_per_tti*10,rxs);
Raymond Knopp's avatar
Raymond Knopp committed
1054 1055 1056
    // wakeup synchronization processing thread
    wakeup_synch(ru);
    ic=0;
1057

Raymond Knopp's avatar
Raymond Knopp committed
1058
    while ((ic>=0)&&(!oai_exit)) {
1059
      // continuously read in frames, 1ms at a time,
Raymond Knopp's avatar
Raymond Knopp committed
1060
      // until we are done with the synchronization procedure
1061
      for (i=0; i<ru->nb_rx; i++)
1062 1063 1064 1065 1066 1067 1068 1069 1070
        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);

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1071
      AssertFatal((ret=pthread_mutex_lock(&ru->proc.mutex_synch))==0,"mutex_lock returns %d\n",ret);
1072
      ic = ru->proc.instance_cnt_synch;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1073
      AssertFatal((ret=pthread_mutex_unlock(&ru->proc.mutex_synch))==0,"mutex_unlock returns %d\n",ret);
Raymond Knopp's avatar
Raymond Knopp committed
1074 1075
    } // ic>=0
  } // in_synch==0
1076 1077

  // read in rx_offset samples
Raymond Knopp's avatar
Raymond Knopp committed
1078 1079 1080 1081 1082
  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,
1083
				   ru->nb_rx);
1084 1085
  // Verification of synchronization procedure
  ru->state = RU_CHECK_SYNC;
Younes's avatar
Younes committed
1086

1087
  LOG_I(PHY,"Exiting synch routine\n");
Raymond Knopp's avatar
Raymond Knopp committed
1088 1089
}

1090
int check_sync(RU_t *ru, RU_t *ru_master, int subframe){
1091

1092 1093 1094 1095
	if (fabs(ru_master->proc.t[subframe].tv_nsec - ru->proc.t[subframe].tv_nsec) > 500000)
		return 0;
	return 1;
}
1096

1097
void wakeup_L1s(RU_t *ru) {
1098 1099
  int i;
  PHY_VARS_eNB **eNB_list = ru->eNB_list;
1100
  LOG_D(PHY,"wakeup_L1s (num %d) for RU %d (%d.%d)\n",ru->num_eNB,ru->idx, ru->proc.frame_rx,ru->proc.subframe_rx);
1101

1102
  PHY_VARS_eNB *eNB=eNB_list[0];
1103
  L1_proc_t *proc      = &eNB->proc;
1104
  struct timespec t;
Raymond Knopp's avatar
Raymond Knopp committed
1105
  LOG_D(PHY,"wakeup_L1s (num %d) for RU %d ru->eNB_top:%p\n",ru->num_eNB,ru->idx, ru->eNB_top);
1106

1107 1108 1109
  // call eNB function directly
  char string[20];
  sprintf(string,"Incoming RU %d",ru->idx);
1110

1111 1112
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_WAKEUP_L1S_RU+ru->idx, ru->proc.frame_rx);
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_WAKEUP_L1S_RU+ru->idx, ru->proc.subframe_rx);
1113
  
1114 1115 1116 1117 1118 1119
  AssertFatal(0==pthread_mutex_lock(&proc->mutex_RU),"");
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_LOCK_MUTEX_RU+ru->idx, 1 );
  
  //printf("wakeup_L1s: Frame %d, Subframe %d: RU %d done (wait_cnt %d),RU_mask[%d] %x\n",
  //          ru->proc.frame_rx,ru->proc.subframe_rx,ru->idx,ru->wait_cnt,ru->proc.subframe_rx,proc->RU_mask[ru->proc.subframe_rx]);
  //    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_WAKEUP_L1S_RU+ru->idx, ru->proc.frame_rx);
magounak's avatar
magounak committed
1120
  //    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_WAKEUP_L1S_RU+ru->idx, ru->proc.subframe_rx);
1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138
  clock_gettime(CLOCK_MONOTONIC,&ru->proc.t[ru->proc.subframe_rx]);
  
  if (proc->RU_mask[ru->proc.subframe_rx] == 0){
    //clock_gettime(CLOCK_MONOTONIC,&proc->t[ru->proc.subframe_rx]);
    proc->t[ru->proc.subframe_rx] = ru->proc.t[ru->proc.subframe_rx];
    //start_meas(&proc->ru_arrival_time);
    LOG_D(PHY,"RU %d starting timer for frame %d subframe %d\n",ru->idx, ru->proc.frame_rx,ru->proc.subframe_rx);
  }
  
  for (i=0;i<eNB->num_RU;i++) {
    if (eNB->RU_list[i]->wait_cnt==1 && ru->proc.subframe_rx!=9) eNB->RU_list[i]->wait_cnt=0;
    LOG_D(PHY,"RU %d has frame %d and subframe %d, state %s\n",eNB->RU_list[i]->idx,eNB->RU_list[i]->proc.frame_rx, eNB->RU_list[i]->proc.subframe_rx, ru_states[eNB->RU_list[i]->state]);
    if (ru == eNB->RU_list[i] && eNB->RU_list[i]->wait_cnt == 0) {
      //	AssertFatal((proc->RU_mask&(1<<i)) == 0, "eNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n",eNB->Mod_id,ru->proc.frame_rx,ru->proc.subframe_rx,ru->idx,eNB->num_RU,proc->RU_mask);
      proc->RU_mask[ru->proc.subframe_rx] |= (1<<i);
    }else if (/*eNB->RU_list[i]->state == RU_SYNC || */
	      (eNB->RU_list[i]->is_slave==1 && eNB->RU_list[i]->wait_cnt>0 && ru!=eNB->RU_list[i] && ru->is_slave==0)){
      proc->RU_mask[ru->proc.subframe_rx] |= (1<<i);
1139
    }
1140 1141 1142 1143
    //printf("RU %d, RU_mask[%d] %d, i %d, frame %d, slave %d, ru->cnt %d, i->cnt %d\n",ru->idx,ru->proc.subframe_rx,proc->RU_mask[ru->proc.subframe_rx],i,ru->proc.frame_rx,ru->is_slave,ru->wait_cnt,eNB->RU_list[i]->wait_cnt);
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_MASK_RU, proc->RU_mask[ru->proc.subframe_rx]);
    if (ru->is_slave == 0 && ( (proc->RU_mask[ru->proc.subframe_rx]&(1<<i)) == 1) && eNB->RU_list[i]->state == RU_RUN) { // This is master & the RRU has already been received
      if (check_sync(eNB->RU_list[i],eNB->RU_list[0],ru->proc.subframe_rx)  == 0)
1144
	LOG_E(PHY,"RU %d is not SYNC, subframe %d, time  %f this is master\n", eNB->RU_list[i]->idx, ru->proc.subframe_rx, fabs(eNB->RU_list[i]->proc.t[ru->proc.subframe_rx].tv_nsec - eNB->RU_list[0]->proc.t[ru->proc.subframe_rx].tv_nsec));
1145 1146 1147
    }else if (ru->is_slave == 1 && ru->state == RU_RUN && ( (proc->RU_mask[ru->proc.subframe_rx]&(1<<0)) == 1)){ // master already received. TODO: we assume that RU0 is master.
      if (check_sync(ru,eNB->RU_list[0],ru->proc.subframe_rx)  == 0)
	LOG_E(PHY,"RU %d is not SYNC time, subframe %d, time  %f\n", ru->idx, ru->proc.subframe_rx, fabs(ru->proc.t[ru->proc.subframe_rx].tv_nsec - eNB->RU_list[0]->proc.t[ru->proc.subframe_rx].tv_nsec));
1148
    }
1149 1150 1151 1152 1153
  }
  //clock_gettime(CLOCK_MONOTONIC,&t);
  //LOG_I(PHY,"RU mask is now %x, time is %lu\n",proc->RU_mask[ru->proc.subframe_rx], t.tv_nsec - proc->t[ru->proc.subframe_rx].tv_nsec);
  
  if (proc->RU_mask[ru->proc.subframe_rx] == (1<<eNB->num_RU)-1) { // all RUs have provided their information so continue on and wakeup eNB top
1154 1155 1156
    LOG_D(PHY,"ru_mask is %d \n ", proc->RU_mask[ru->proc.subframe_rx]);
    LOG_D(PHY,"the number of RU is %d, the current ru is RU %d \n ", (1<<eNB->num_RU)-1, ru->idx);
    LOG_D(PHY,"ru->proc.subframe_rx is %d \n", ru->proc.subframe_rx);
1157 1158 1159 1160 1161
    LOG_D(PHY,"Reseting mask frame %d, subframe %d, this is RU %d\n",ru->proc.frame_rx, ru->proc.subframe_rx, ru->idx);
    proc->RU_mask[ru->proc.subframe_rx] = 0;
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_MASK_RU, proc->RU_mask[ru->proc.subframe_rx]);
    clock_gettime(CLOCK_MONOTONIC,&t);
    //stop_meas(&proc->ru_arrival_time);
1162
    /*    AssertFatal(t.tv_nsec < proc->t[ru->proc.subframe_rx].tv_nsec+5000000,
1163 1164
		"Time difference for subframe %d (Frame %d) => %lu > 5ms, this is RU %d\n",
		ru->proc.subframe_rx, ru->proc.frame_rx, t.tv_nsec - proc->t[ru->proc.subframe_rx].tv_nsec, ru->idx);
1165
    */
1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183
    // VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_WAKEUP_L1S_RU+ru->idx, ru->proc.frame_rx);
    //VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_WAKEUP_L1S_RU+ru->idx, ru->proc.subframe_rx);
    AssertFatal(0==pthread_mutex_unlock(&proc->mutex_RU),"");
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_LOCK_MUTEX_RU+ru->idx, 0 );
    
    // unlock RUs that are waiting for eNB processing to be completed
    LOG_D(PHY,"RU %d wakeup eNB top for subframe %d\n", ru->idx,ru->proc.subframe_rx);
    if (ru->wait_cnt == 0) {
      if (ru->num_eNB==1 && ru->eNB_top!=0 && get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD)
	ru->eNB_top(eNB_list[0],proc->frame_rx,proc->subframe_rx,string,ru);
      else {
	for (i=0;i<ru->num_eNB;i++) {
	  eNB_list[i]->proc.ru_proc = &ru->proc;
	  if (ru->wakeup_rxtx!=0 && ru->wakeup_rxtx(eNB_list[i],ru) < 0)
	    {
	      LOG_E(PHY,"could not wakeup eNB rxtx process for subframe %d\n", ru->proc.subframe_rx);
	    }
	}
1184
      }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1185
    }
1186
    /*
1187
      AssertFatal(0==pthread_mutex_lock(&ruproc->mutex_eNBs),"");
1188
      LOG_D(PHY,"RU %d sending signal to unlock waiting ru_threads\n", ru->idx);
1189 1190 1191
      AssertFatal(0==pthread_cond_broadcast(&ruproc->cond_eNBs),"");
      if (ruproc->instance_cnt_eNBs==-1) ruproc->instance_cnt_eNBs++;
      AssertFatal(0==pthread_mutex_unlock(&ruproc->mutex_eNBs),"");
1192
    */
1193
    }
1194
    else{ // not all RUs have provided their information  
magounak's avatar
magounak committed
1195
    AssertFatal(0==pthread_mutex_unlock(&proc->mutex_RU),"");
magounak's avatar
magounak committed
1196
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_LOCK_MUTEX_RU+ru->idx, 0 );
1197
  }
1198 1199 1200
//      pthread_mutex_unlock(&proc->mutex_RU);
//      LOG_D(PHY,"wakeup eNB top for for subframe %d\n", ru->proc.subframe_rx);
//      ru->eNB_top(eNB_list[0],ru->proc.frame_rx,ru->proc.subframe_rx,string);
1201

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1202
    ru->proc.emulate_rf_busy = 0;
1203
  
1204
}
laurent's avatar
laurent committed
1205 1206

void  wakeup_prach_ru(RU_t *ru) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1207
  int ret;
1208
  struct timespec wait;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1209
  int time_ns = 5000000L;
1210

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1211 1212
  clock_gettime(CLOCK_REALTIME,&wait);
  wait.tv_nsec += time_ns;
1213 1214 1215 1216
  if(wait.tv_nsec >= 1000*1000*1000)
  {
    wait.tv_nsec -= 1000*1000*1000;
    wait.tv_sec  += 1;
1217
  }
1218 1219
  AssertFatal((ret=pthread_mutex_timedlock(&ru->proc.mutex_prach,&wait)) == 0,"[RU] ERROR pthread_mutex_lock for RU prach thread (IC %d)\n", ru->proc.instance_cnt_prach);

1220

1221 1222 1223 1224
  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;
1225

1226
    // DJP - think prach_procedures() is looking at eNB frame_prach
1227 1228 1229 1230
    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;
    }
1231

1232
    LOG_D(PHY,"RU %d: waking up PRACH thread\n",ru->idx);
1233 1234
    // 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");
1235
  } else LOG_W(PHY,"RU prach thread busy, skipping\n");
1236

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1237
  AssertFatal((ret=pthread_mutex_unlock( &ru->proc.mutex_prach ))==0,"mutex_unlock returns %d\n",ret);
1238 1239
}

1240
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
laurent's avatar
laurent committed
1241
void wakeup_prach_ru_br(RU_t *ru) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1242
  int ret;
1243
  struct timespec wait;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1244
  int time_ns = 5000000L;
1245

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1246 1247 1248

  clock_gettime(CLOCK_REALTIME,&wait);
  wait.tv_nsec += time_ns;
1249 1250 1251 1252
  if(wait.tv_nsec >= 1000*1000*1000)
  {
    wait.tv_nsec -= 1000*1000*1000;
    wait.tv_sec  += 1;
1253
  }
1254
  AssertFatal((ret=pthread_mutex_timedlock(&ru->proc.mutex_prach_br,&wait))==0,"[RU] ERROR pthread_mutex_lock for RU prach thread BR (IC %d)\n", ru->proc.instance_cnt_prach_br);
1255

1256

1257 1258 1259 1260 1261 1262 1263
  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");
1264
  } else LOG_W(PHY,"RU prach thread busy, skipping\n");
1265

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1266
  AssertFatal((ret=pthread_mutex_unlock( &ru->proc.mutex_prach_br ))==0,"mutex_unlock returns %d\n",ret);
1267 1268 1269
}
#endif

Raymond Knopp's avatar
Raymond Knopp committed
1270 1271 1272 1273 1274
// 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;
1275
  //printf("////////////////numerology in config = %d\n",numerology);
1276
  int numerology = get_softmodem_params()->numerology;
1277

Raymond Knopp's avatar
Raymond Knopp committed
1278
  if(fp->N_RB_DL == 100) {
1279
    if(numerology == 0) {
1280 1281
      if (fp->threequarter_fs) {
        cfg->sample_rate=23.04e6;
1282
        cfg->samples_per_frame = 230400;
1283 1284
        cfg->tx_bw = 10e6;
        cfg->rx_bw = 10e6;
1285
      } else {
1286
        cfg->sample_rate=30.72e6;
1287
        cfg->samples_per_frame = 307200;
1288 1289 1290
        cfg->tx_bw = 10e6;
        cfg->rx_bw = 10e6;
      }
1291 1292 1293
    } else if(numerology == 1) {
      cfg->sample_rate=61.44e6;
      cfg->samples_per_frame = 307200;
1294 1295
      cfg->tx_bw = 20e6;
      cfg->rx_bw = 20e6;
1296 1297 1298
    } else if(numerology == 2) {
      cfg->sample_rate=122.88e6;
      cfg->samples_per_frame = 307200;
1299 1300
      cfg->tx_bw = 40e6;
      cfg->rx_bw = 40e6;
1301 1302 1303 1304
    } else {
      printf("Wrong input for numerology %d\n setting to 20MHz normal CP configuration",numerology);
      cfg->sample_rate=30.72e6;
      cfg->samples_per_frame = 307200;
Raymond Knopp's avatar
Raymond Knopp committed
1305 1306
      cfg->tx_bw = 10e6;
      cfg->rx_bw = 10e6;
1307
    }
Raymond Knopp's avatar
Raymond Knopp committed
1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322
  } 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;
1323
  } else AssertFatal(1==0,"Unknown N_RB_DL %d\n",fp->N_RB_DL);
Raymond Knopp's avatar
Raymond Knopp committed
1324

1325

Raymond Knopp's avatar
Raymond Knopp committed
1326 1327 1328 1329 1330 1331 1332 1333 1334
  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;
1335
  cfg->clock_source=get_softmodem_params()->clock_source;
1336

Raymond Knopp's avatar
Raymond Knopp committed
1337 1338 1339
  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
1340 1341
    cfg->tx_gain[i] = (double)ru->att_tx;
    cfg->rx_gain[i] = ru->max_rxgain-(double)ru->att_rx;
Raymond Knopp's avatar
Raymond Knopp committed
1342 1343
    cfg->configFilename = rf_config_file;
    printf("channel %d, Setting tx_gain offset %f, rx_gain offset %f, tx_freq %f, rx_freq %f\n",
1344 1345 1346 1347
           i, cfg->tx_gain[i],
           cfg->rx_gain[i],
           cfg->tx_freq[i],
           cfg->rx_freq[i]);
Raymond Knopp's avatar
Raymond Knopp committed
1348 1349 1350 1351 1352 1353 1354 1355
  }
}

/* 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) {
1356
  int i,j;
Raymond Knopp's avatar
Raymond Knopp committed
1357 1358 1359
  int card,ant;
  //uint16_t N_TA_offset = 0;
  LTE_DL_FRAME_PARMS *frame_parms;
1360

Raymond Knopp's avatar
Raymond Knopp committed
1361 1362 1363 1364
  if (ru) {
    frame_parms = &ru->frame_parms;
    printf("setup_RU_buffers: frame_parms = %p\n",frame_parms);
  } else {
1365
    printf("RU not initialized (NULL pointer)\n");
Raymond Knopp's avatar
Raymond Knopp committed
1366 1367
    return(-1);
  }
1368

1369 1370 1371 1372
  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;
1373

1374 1375 1376 1377 1378
    if(IS_SOFTMODEM_BASICSIM)
      /* this is required for the basic simulator in TDD mode
       * TODO: find a proper cleaner solution
       */
      ru->N_TA_offset = 0;
1379 1380

    if      (frame_parms->N_RB_DL == 100) /* no scaling to do */;
1381 1382 1383 1384 1385 1386 1387 1388 1389 1390
    else if (frame_parms->N_RB_DL == 50) {
      ru->sf_extension       /= 2;
      ru->end_of_burst_delay /= 2;
    } else if (frame_parms->N_RB_DL == 25) {
      ru->sf_extension       /= 4;
      ru->end_of_burst_delay /= 4;
    } else {
      printf("not handled, todo\n");
      exit(1);
    }
1391 1392 1393
  } else {
    ru->N_TA_offset = 0;
    ru->sf_extension = 0;
1394
    ru->end_of_burst_delay = 0;
1395 1396
  }

Raymond Knopp's avatar
Raymond Knopp committed
1397 1398 1399 1400 1401 1402 1403 1404 1405
  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[ru->rf_map.chain+ant];
      printf("rxdata[%d] @ %p\n",i,ru->common.rxdata[i]);
1406

Raymond Knopp's avatar
Raymond Knopp committed
1407
      for (j=0; j<16; j++) {
1408 1409
        printf("rxbuffer %d: %x\n",j,ru->common.rxdata[i][j]);
        ru->common.rxdata[i][j] = 16-j;
Raymond Knopp's avatar
Raymond Knopp committed
1410 1411
      }
    }
1412

Raymond Knopp's avatar
Raymond Knopp committed
1413 1414 1415 1416 1417 1418 1419
    for (i=0; i<ru->nb_tx; i++) {
      card = i/4;
      ant = i%4;
      printf("Mapping RU id %d, tx_ant %d, on card %d, chain %d\n",ru->idx,i,ru->rf_map.card+card, ru->rf_map.chain+ant);
      free(ru->common.txdata[i]);
      ru->common.txdata[i] = ru->openair0_cfg.txbase[ru->rf_map.chain+ant];
      printf("txdata[%d] @ %p\n",i,ru->common.txdata[i]);
1420

Raymond Knopp's avatar
Raymond Knopp committed
1421
      for (j=0; j<16; j++) {
1422 1423
        printf("txbuffer %d: %x\n",j,ru->common.txdata[i][j]);
        ru->common.txdata[i][j] = 16-j;
Raymond Knopp's avatar
Raymond Knopp committed
1424 1425
      }
    }
1426
  } else { // not memory-mapped DMA
Raymond Knopp's avatar
Raymond Knopp committed
1427 1428
    //nothing to do, everything already allocated in lte_init
  }
1429

Raymond Knopp's avatar
Raymond Knopp committed
1430 1431 1432
  return(0);
}

1433
void* ru_stats_thread(void* param) {
1434 1435 1436 1437

  RU_t               *ru      = (RU_t*)param;

  wait_sync("ru_stats_thread");
1438
  
1439
  while (!oai_exit) {
1440 1441 1442 1443 1444 1445
    sleep(1);
    if (opp_enabled) {
      if (ru->feprx) print_meas(&ru->ofdm_demod_stats,"feprx",NULL,NULL);
      if (ru->feptx_ofdm) print_meas(&ru->ofdm_mod_stats,"feptx_ofdm",NULL,NULL);
      if (ru->fh_north_asynch_in) print_meas(&ru->rx_fhaul,"rx_fhaul",NULL,NULL);
      if (ru->fh_north_out) {
1446 1447 1448 1449
	print_meas(&ru->tx_fhaul,"tx_fhaul",NULL,NULL);
	print_meas(&ru->compression,"compression",NULL,NULL);
	print_meas(&ru->transport,"transport",NULL,NULL);
	LOG_I(PHY,"ru->north_out_cnt = %d\n",ru->north_out_cnt);
1450
      }
1451 1452 1453
      if (ru->fh_south_out) LOG_I(PHY,"ru->south_out_cnt = %d\n",ru->south_out_cnt);
      if (ru->fh_north_asynch_in) LOG_I(PHY,"ru->north_in_cnt = %d\n",ru->north_in_cnt);
      
1454
    }
1455
  }
1456
  
1457
  return(NULL);
1458 1459
}

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1460
#ifdef PHY_TX_THREAD
1461 1462 1463
  int first_phy_tx = 1;
  volatile int16_t phy_tx_txdataF_end;
  volatile int16_t phy_tx_end;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1464 1465
#endif

1466
void *ru_thread_tx( void *param ) {
1467
  RU_t *ru              = (RU_t *)param;
1468 1469
  RU_proc_t *proc       = &ru->proc;
  PHY_VARS_eNB *eNB;
1470 1471
  L1_proc_t *eNB_proc;
  L1_rxtx_proc_t *L1_proc;
1472 1473
  cpu_set_t cpuset;
  CPU_ZERO(&cpuset);
1474 1475 1476
  thread_top_init("ru_thread_tx",1,400000,500000,500000);
  //CPU_SET(5, &cpuset);
  //pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
1477
  //wait_sync("ru_thread_tx");
1478
  wait_on_condition(&proc->mutex_FH1,&proc->cond_FH1,&proc->instance_cnt_FH1,"ru_thread_tx");
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1479
  int ret;
1480

1481 1482
  while (!oai_exit) {
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_CPUID_RU_THREAD_TX,sched_getcpu());
1483

1484
    if (oai_exit) break;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1485

1486
    LOG_D(PHY,"ru_thread_tx (ru %d): Waiting for TX processing\n",ru->idx);
1487
    // wait until eNBs are finished subframe RX n and TX n+4
1488
    wait_on_condition(&proc->mutex_eNBs,&proc->cond_eNBs,&proc->instance_cnt_eNBs,"ru_thread_tx");
1489

1490 1491
    LOG_D(PHY,"ru_thread_tx: TX in %d.%d\n",ru->proc.frame_tx,ru->proc.subframe_tx);

WANG Tsu-Han's avatar
WANG Tsu-Han committed
1492
    if (oai_exit) break;
1493

1494 1495
    // do TX front-end processing if needed (precoding and/or IDFTs)
    if (ru->feptx_prec) ru->feptx_prec(ru);
1496

1497 1498
    // do OFDM if needed
    if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru);
1499 1500

    if(!(get_softmodem_params()->emulate_rf)) {
1501 1502
      // do outgoing fronthaul (south) if needed
      if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru);
1503
    }
1504
    LOG_D(PHY,"ru_thread_tx: releasing RU TX in %d.%d\n",proc->frame_tx,proc->subframe_tx);
1505
    release_thread(&proc->mutex_eNBs,&proc->instance_cnt_eNBs,"ru_thread_tx");
1506 1507

    for(int i = 0; i<ru->num_eNB; i++) {
1508 1509 1510
      eNB       = ru->eNB_list[i];
      eNB_proc  = &eNB->proc;
      L1_proc   = (get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT)? &eNB_proc->L1_proc_tx : &eNB_proc->L1_proc;
1511

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1512
      AssertFatal((ret=pthread_mutex_lock(&eNB_proc->mutex_RU_tx))==0,"mutex_lock returns %d\n",ret);
1513
      for (int j=0; j<eNB->num_RU; j++) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1514
        if (ru == eNB->RU_list[j]) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1515
          if ((eNB_proc->RU_mask_tx&(1<<j)) > 0)
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1516
            LOG_E(PHY,"eNB %d frame %d, subframe %d : previous information from RU tx %d (num_RU %d,mask %x) has not been served yet!\n",
1517 1518
                  eNB->Mod_id,eNB_proc->frame_rx,eNB_proc->subframe_rx,ru->idx,eNB->num_RU,eNB_proc->RU_mask_tx);

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1519
          eNB_proc->RU_mask_tx |= (1<<j);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1520
        }
1521
        else if (/*eNB->RU_list[j]->state==RU_SYNC ||*/ (eNB->RU_list[j]->is_slave==1 && eNB->RU_list[j]->wait_cnt>0 && ru!=eNB->RU_list[j] && ru->is_slave==0)){
magounak's avatar
magounak committed
1522
		eNB_proc->RU_mask_tx |= (1<<j);
1523
        }
magounak's avatar
magounak committed
1524
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_MASK_TX_RU, eNB_proc->RU_mask_tx);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1525 1526
      }
      if (eNB_proc->RU_mask_tx != (1<<eNB->num_RU)-1) {  // not all RUs have provided their information so return
magounak's avatar
magounak committed
1527
      	//printf("Not all RUs have provided their info (mask = %d), RU %d, num_RUs %d\n", eNB_proc->RU_mask_tx,ru->idx,eNB->num_RU);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1528
        AssertFatal((ret=pthread_mutex_unlock(&eNB_proc->mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret);
1529
      } else { // all RUs TX are finished so send the ready signal to eNB processing
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1530
        eNB_proc->RU_mask_tx = 0;
magounak's avatar
magounak committed
1531
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_MASK_TX_RU, eNB_proc->RU_mask_tx);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1532 1533
        AssertFatal((ret=pthread_mutex_unlock(&eNB_proc->mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret);
        AssertFatal((ret=pthread_mutex_lock( &L1_proc->mutex_RUs))==0,"mutex_lock returns %d\n",ret);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1534
        L1_proc->instance_cnt_RUs = 0;
1535

1536
        LOG_D(PHY,"ru_thread_tx: Signaling RU TX done in %d.%d\n",proc->frame_tx,proc->subframe_tx);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1537
        // the thread can now be woken up
Raymond Knopp's avatar
Raymond Knopp committed
1538
        LOG_D(PHY,"ru_thread_tx: clearing mask and Waking up L1 thread\n"); 
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1539 1540 1541 1542
        if (pthread_cond_signal(&L1_proc->cond_RUs) != 0) {
          LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n");
          exit_fun( "ERROR pthread_cond_signal" );
        }
1543

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1544
        AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex_RUs))==0,"mutex_unlock returns %d\n",ret);
1545
      }
1546
    }
magounak's avatar
magounak committed
1547 1548
    //printf("ru_thread_tx: Frame %d, Subframe %d: RU %d done (wait_cnt %d),RU_mask_tx %d\n",
      //    eNB_proc->frame_rx,eNB_proc->subframe_rx,ru->idx,ru->wait_cnt,eNB_proc->RU_mask_tx);
1549
  }
1550

1551
  release_thread(&proc->mutex_FH1,&proc->instance_cnt_FH1,"ru_thread_tx");
1552 1553 1554
  return 0;
}

1555
void *ru_thread( void *param ) {
1556
  RU_t               *ru      = (RU_t *)param;
1557 1558
  RU_proc_t          *proc    = &ru->proc;
  LTE_DL_FRAME_PARMS *fp      = &ru->frame_parms;
1559
  int                subframe =9;
1560
  int                frame    =1023;
Raymond Knopp's avatar
Raymond Knopp committed
1561
  int                   resynch_done = 0;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1562
  int                ret;
1563 1564
  cpu_set_t cpuset;
  CPU_ZERO(&cpuset);
Raymond Knopp's avatar
Raymond Knopp committed
1565
  // set default return value
Raymond Knopp's avatar
Raymond Knopp committed
1566

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1567 1568 1569
#if defined(PRE_SCD_THREAD)
  dlsch_ue_select_tbl_in_use = 1;
#endif
Raymond Knopp's avatar
Raymond Knopp committed
1570
  // set default return value
1571
  thread_top_init("ru_thread",1,400000,500000,500000);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1572 1573
  //CPU_SET(1, &cpuset);
  //pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
1574 1575
  pthread_setname_np( pthread_self(),"ru thread");
  LOG_I(PHY,"thread ru created id=%ld\n", syscall(__NR_gettid));
1576
  LOG_I(PHY,"Starting RU %d (%s,%s),\n",ru->idx,eNB_functions[ru->function],eNB_timing[ru->if_timing]);
Raymond Knopp's avatar
Raymond Knopp committed
1577
  
1578
  if(get_softmodem_params()->emulate_rf) {
1579 1580 1581
    fill_rf_config(ru,ru->rf_config_file);
    init_frame_parms(&ru->frame_parms,1);
    phy_init_RU(ru);
Raymond Knopp's avatar
Raymond Knopp committed
1582
    
1583
    if (setup_RU_buffers(ru)!=0) {
1584 1585
      printf("Exiting, cannot initialize RU Buffers\n");
      exit(-1);
1586
    }
Raymond Knopp's avatar
Raymond Knopp committed
1587
    
1588
    LOG_I(PHY, "Signaling main thread that RU %d is ready\n",ru->idx);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1589
    AssertFatal((ret=pthread_mutex_lock(&RC.ru_mutex))==0,"mutex_lock returns %d\n",ret);
1590 1591
    RC.ru_mask &= ~(1<<ru->idx);
    pthread_cond_signal(&RC.ru_cond);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1592
    AssertFatal((ret=pthread_mutex_unlock(&RC.ru_mutex))==0,"mutex_unlock returns %d\n",ret);
Raymond Knopp's avatar
Raymond Knopp committed
1593
    ru->state = RU_RUN;
1594
  }
Raymond Knopp's avatar
Raymond Knopp committed
1595
  else if (ru->has_ctrl_prt == 0){
1596 1597 1598
    // There is no control port: start everything here
    LOG_I(PHY, "RU %d has not ctrl port\n",ru->idx);
    if (ru->if_south == LOCAL_RF){
1599 1600
      fill_rf_config(ru,ru->rf_config_file);
      init_frame_parms(&ru->frame_parms,1);
1601
      ru->frame_parms.nb_antennas_rx = ru->nb_rx;
1602
      phy_init_RU(ru);
1603 1604
      
      
1605
      openair0_device_load(&ru->rfdevice,&ru->openair0_cfg);
1606 1607 1608 1609 1610
      
      if (setup_RU_buffers(ru)!=0) {
	printf("Exiting, cannot initialize RU Buffers\n");
	exit(-1);
      }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1611
      AssertFatal((ret=pthread_mutex_lock(&RC.ru_mutex))==0,"mutex_lock returns %d\n",ret);
1612 1613
      RC.ru_mask &= ~(1<<ru->idx);
      pthread_cond_signal(&RC.ru_cond);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1614
      AssertFatal((ret=pthread_mutex_unlock(&RC.ru_mutex))==0,"mutex_unlock returns %d\n",ret);
1615
    }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1616
    AssertFatal((ret=pthread_mutex_lock(&RC.ru_mutex))==0,"mutex_lock returns %d\n",ret);
1617 1618
    RC.ru_mask &= ~(1<<ru->idx);
    pthread_cond_signal(&RC.ru_cond);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1619
    AssertFatal((ret=pthread_mutex_unlock(&RC.ru_mutex))==0,"mutex_unlock returns %d\n",ret);
1620 1621 1622 1623
    
    ru->state = RU_RUN;
    
    
1624
  }
Raymond Knopp's avatar
Raymond Knopp committed
1625
  
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1626
  AssertFatal((ret=pthread_mutex_lock(&proc->mutex_FH1))==0,"mutex_lock returns %d\n",ret);
1627 1628
  proc->instance_cnt_FH1 = 0;
  pthread_cond_signal(&proc->cond_FH1);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1629
  AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_FH1))==0,"mutex_unlock returns %d\n",ret);
1630

Raymond Knopp's avatar
Raymond Knopp committed
1631
  while (!oai_exit) {
Raymond Knopp's avatar
Raymond Knopp committed
1632
    
1633
    if (ru->if_south != LOCAL_RF && ru->is_slave==1) {
Raymond Knopp's avatar
Raymond Knopp committed
1634
      ru->wait_cnt = 100;
1635 1636
    }
    else { 
Raymond Knopp's avatar
Raymond Knopp committed
1637 1638
      ru->wait_cnt = 0;
      ru->wait_check = 0;
1639
    }
Raymond Knopp's avatar
Raymond Knopp committed
1640 1641
    
    
Raymond Knopp's avatar
Raymond Knopp committed
1642 1643 1644 1645 1646
    // wait to be woken up
    if (ru->function!=eNodeB_3GPP && ru->has_ctrl_prt == 1) {
      if (wait_on_condition(&ru->proc.mutex_ru,&ru->proc.cond_ru_thread,&ru->proc.instance_cnt_ru,"ru_thread")<0) break;
    }
    else wait_sync("ru_thread");
Raymond Knopp's avatar
Raymond Knopp committed
1647
    
1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658
    if(!(get_softmodem_params()->emulate_rf)) {
      if (ru->is_slave == 0) AssertFatal(ru->state == RU_RUN,"ru-%d state = %s != RU_RUN\n",ru->idx,ru_states[ru->state]);
      else if (ru->is_slave == 1) AssertFatal(ru->state == RU_SYNC || ru->state == RU_RUN || ru->state == RU_CHECK_SYNC,"ru %d state = %s != RU_SYNC or RU_RUN or RU_CHECK_SYNC\n",ru->idx,ru_states[ru->state]); 
      // Start RF device if any
      if (ru->start_rf) {
	if (ru->start_rf(ru) != 0)
	  LOG_E(HW,"Could not start the RF device\n");
	else LOG_I(PHY,"RU %d rf device ready\n",ru->idx);
      }
      else LOG_D(PHY,"RU %d no rf device\n",ru->idx);
    }
1659 1660
    // if an asnych_rxtx thread exists
    // wakeup the thread because the devices are ready at this point
Raymond Knopp's avatar
Raymond Knopp committed
1661
    
1662
    if ((ru->fh_south_asynch_in)||(ru->fh_north_asynch_in)) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1663
      AssertFatal((ret=pthread_mutex_lock(&proc->mutex_asynch_rxtx))==0,"mutex_lock returns %d\n",ret);
1664 1665
      proc->instance_cnt_asynch_rxtx=0;
      pthread_cond_signal(&proc->cond_asynch_rxtx);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1666
      AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_asynch_rxtx))==0,"mutex_unlock returns %d\n",ret);
1667
    } else LOG_D(PHY,"RU %d no asynch_south interface\n",ru->idx);
Raymond Knopp's avatar
Raymond Knopp committed
1668
    
1669
    // if this is a slave RRU, try to synchronize on the DL frequency
Raymond Knopp's avatar
Raymond Knopp committed
1670
    if ((ru->is_slave == 1) && (ru->if_south == LOCAL_RF)) do_ru_synch(ru);
Raymond Knopp's avatar
Raymond Knopp committed
1671
    
1672
    LOG_D(PHY,"Starting steady-state operation\n");
Raymond Knopp's avatar
Raymond Knopp committed
1673
    // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices
1674
    while (ru->state == RU_RUN || ru->state == RU_CHECK_SYNC) {
Raymond Knopp's avatar
Raymond Knopp committed
1675
      
Raymond Knopp's avatar
Raymond Knopp committed
1676 1677
      // these are local subframe/frame counters to check that we are in synch with the fronthaul timing.
      // They are set on the first rx/tx in the underly FH routines.
Raymond Knopp's avatar
Raymond Knopp committed
1678 1679 1680 1681
      if (subframe==9) {
        subframe=0;
        frame++;
        frame&=1023;
1682
      } else {
Raymond Knopp's avatar
Raymond Knopp committed
1683
        subframe++;
1684
      }
Raymond Knopp's avatar
Raymond Knopp committed
1685
      
Raymond Knopp's avatar
Raymond Knopp committed
1686
      // synchronization on input FH interface, acquire signals/data and block
1687
      if (ru->fh_south_in) ru->fh_south_in(ru,&frame,&subframe);
Raymond Knopp's avatar
Raymond Knopp committed
1688
      else AssertFatal(1==0, "No fronthaul interface at south port");
Raymond Knopp's avatar
Raymond Knopp committed
1689
      
1690 1691
#ifdef PHY_TX_THREAD
      if(first_phy_tx == 0)
1692
	{ 
1693 1694
	  phy_tx_end = 0;
	  phy_tx_txdataF_end = 0;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1695 1696
          AssertFatal((ret=pthread_mutex_lock(&ru->proc.mutex_phy_tx))==0,"[RU] ERROR pthread_mutex_lock for phy tx thread (IC %d)\n", ru->proc.instance_cnt_phy_tx);

1697 1698 1699 1700 1701 1702 1703 1704 1705
	  if (ru->proc.instance_cnt_phy_tx==-1) {
	    ++ru->proc.instance_cnt_phy_tx;
	    
	    // the thread can now be woken up
	    AssertFatal(pthread_cond_signal(&ru->proc.cond_phy_tx) == 0, "ERROR pthread_cond_signal for phy_tx thread\n");
	  }else{
	    LOG_E(PHY,"phy tx thread busy, skipping\n");
	    ++ru->proc.instance_cnt_phy_tx;
	  }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1706
          AssertFatal((ret=pthread_mutex_unlock( &ru->proc.mutex_phy_tx ))==0,"mutex_unlock returns %d\n",ret);
1707
	} else { 
1708 1709 1710 1711
        phy_tx_end = 1;
        phy_tx_txdataF_end = 1;
      }
      first_phy_tx = 0;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1712
#endif
1713
      
Raymond Knopp's avatar
Raymond Knopp committed
1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727
      if (ru->stop_rf && ru->cmd == STOP_RU) {
        ru->stop_rf(ru);
        ru->state = RU_IDLE;
        ru->cmd   = EMPTY;
        LOG_I(PHY,"RU %d rf device stopped\n",ru->idx);
        break;
      }
      else if (ru->cmd == STOP_RU) {
        ru->state = RU_IDLE;
        ru->cmd   = EMPTY;
        LOG_I(PHY,"RU %d stopped\n",ru->idx);
        break;
      }
      if (oai_exit == 1) break;
Raymond Knopp's avatar
Raymond Knopp committed
1728
      
1729
      if (ru->wait_cnt > 0) {
Raymond Knopp's avatar
Raymond Knopp committed
1730
	
Raymond Knopp's avatar
Raymond Knopp committed
1731
        ru->wait_cnt--;
1732
        LOG_D(PHY,"RU thread %d, frame %d, subframe %d, wait_cnt %d \n",ru->idx, frame, subframe, ru->wait_cnt);
Raymond Knopp's avatar
Raymond Knopp committed
1733
	
Raymond Knopp's avatar
Raymond Knopp committed
1734
        if (ru->if_south!=LOCAL_RF && ru->wait_cnt <=20 && subframe == 5 && frame != RC.ru[0]->proc.frame_rx && resynch_done == 0) {
Raymond Knopp's avatar
Raymond Knopp committed
1735
	  // Send RRU_frame adjust
Raymond Knopp's avatar
Raymond Knopp committed
1736 1737 1738 1739 1740
          RRU_CONFIG_msg_t rru_config_msg;
          rru_config_msg.type = RRU_frame_resynch;
          rru_config_msg.len  = sizeof(RRU_CONFIG_msg_t); // TODO: set to correct msg len
          ((uint16_t*)&rru_config_msg.msg[0])[0] = RC.ru[0]->proc.frame_rx;
          ru->cmd=WAIT_RESYNCH;
1741
          LOG_I(PHY,"Sending Frame Resynch %d to RRU %d\n", RC.ru[0]->proc.frame_rx,ru->idx);
Raymond Knopp's avatar
Raymond Knopp committed
1742 1743 1744
          AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),"Failed to send msg to RAU\n");
          resynch_done=1;
        }
1745
        wakeup_L1s(ru);
Raymond Knopp's avatar
Raymond Knopp committed
1746
      }
Raymond Knopp's avatar
Raymond Knopp committed
1747
      else {
Raymond Knopp's avatar
Raymond Knopp committed
1748
	
magounak's avatar
magounak committed
1749
        LOG_D(PHY,"RU thread %d, frame %d, subframe %d \n",
Raymond Knopp's avatar
Raymond Knopp committed
1750
              ru->idx,frame,subframe);
Raymond Knopp's avatar
Raymond Knopp committed
1751
	
1752
        if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)==1)) {
Raymond Knopp's avatar
Raymond Knopp committed
1753 1754
          LOG_D(PHY,"Waking up prach for %d.%d\n",proc->frame_rx,proc->subframe_rx);
          wakeup_prach_ru(ru);
1755
        }
Raymond Knopp's avatar
Raymond Knopp committed
1756 1757
	
	
1758
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
Raymond Knopp's avatar
Raymond Knopp committed
1759
        else if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)>1))
Raymond Knopp's avatar
Raymond Knopp committed
1760
          wakeup_prach_ru_br(ru);
1761
#endif
Raymond Knopp's avatar
Raymond Knopp committed
1762 1763 1764 1765 1766 1767 1768 1769
	
	// adjust for timing offset between RU
	if (ru->idx!=0) proc->frame_tx = (proc->frame_tx+proc->frame_offset)&1023;
	
	// At this point, all information for subframe has been received on FH interface
	// If this proc is to provide synchronization, do so
	wakeup_slaves(proc);
	
1770
        // do RX front-end processing (frequency-shift, dft) if needed
1771
	if (ru->feprx) ru->feprx(ru);
Raymond Knopp's avatar
Raymond Knopp committed
1772
	
1773
        // wakeup all eNB processes waiting for this RU
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1774
        AssertFatal((ret=pthread_mutex_lock(&proc->mutex_eNBs))==0,"mutex_lock returns %d\n",ret);
1775
	if (proc->instance_cnt_eNBs==0) proc->instance_cnt_eNBs--;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1776
        AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_eNBs))==0,"mutex_unlock returns %d\n",ret);
Raymond Knopp's avatar
Raymond Knopp committed
1777
	
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1778
#if defined(PRE_SCD_THREAD)
1779 1780 1781 1782
	new_dlsch_ue_select_tbl_in_use = dlsch_ue_select_tbl_in_use;
	dlsch_ue_select_tbl_in_use = !dlsch_ue_select_tbl_in_use;
	memcpy(&pre_scd_eNB_UE_stats,&RC.mac[ru->eNB_list[0]->Mod_id]->UE_list.eNB_UE_stats, sizeof(eNB_UE_STATS)*MAX_NUM_CCs*NUMBER_OF_UE_MAX);
	memcpy(&pre_scd_activeUE, &RC.mac[ru->eNB_list[0]->Mod_id]->UE_list.active, sizeof(boolean_t)*NUMBER_OF_UE_MAX);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1783
        AssertFatal((ret=pthread_mutex_lock(&ru->proc.mutex_pre_scd))==0,"[eNB] error locking proc mutex for eNB pre scd\n");
1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795
	
	ru->proc.instance_pre_scd++;
	
	if (ru->proc.instance_pre_scd == 0) {
	  if (pthread_cond_signal(&ru->proc.cond_pre_scd) != 0) {
	    LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB pre scd\n" );
	    exit_fun( "ERROR pthread_cond_signal cond_pre_scd" );
	  }
	}else{
	  LOG_E( PHY, "[eNB] frame %d subframe %d rxtx busy instance_pre_scd %d\n",
		 frame,subframe,ru->proc.instance_pre_scd );
	}
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1796 1797

	AssertFatal((ret=pthread_mutex_unlock(&ru->proc.mutex_pre_scd))==0,"[eNB] error unlocking mutex_pre_scd mutex for eNB pre scd\n");
1798

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1799
#endif
Raymond Knopp's avatar
Raymond Knopp committed
1800 1801 1802
	// wakeup all eNB processes waiting for this RU
	if (ru->num_eNB>0) wakeup_L1s(ru);
	
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1803
#ifndef PHY_TX_THREAD
Raymond Knopp's avatar
Raymond Knopp committed
1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821
	
	if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD || ru->num_eNB==0) {
	  // do TX front-end processing if needed (precoding and/or IDFTs)
	  if (ru->feptx_prec) ru->feptx_prec(ru);
	  
	  // do OFDM if needed
	  if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru);
	  
	  if(!(get_softmodem_params()->emulate_rf)) {
	    // do outgoing fronthaul (south) if needed
	    if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru);
	    
	    if ((ru->fh_north_out) && (ru->state!=RU_CHECK_SYNC)) ru->fh_north_out(ru);
	  }
	  
	  proc->emulate_rf_busy = 0;
	}
	
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1822
#else
1823 1824 1825 1826 1827 1828 1829 1830
	struct timespec time_req, time_rem;
	time_req.tv_sec = 0;
	time_req.tv_nsec = 10000;
	
	while((!oai_exit)&&(phy_tx_end == 0)){
	  nanosleep(&time_req,&time_rem);
	  continue;
	}
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1831
#endif
1832
      } // else wait_cnt == 0
1833
    } // ru->state = RU_RUN
1834
  } // while !oai_exit
Raymond Knopp's avatar
Raymond Knopp committed
1835
  
Raymond Knopp's avatar
Raymond Knopp committed
1836
  printf( "Exiting ru_thread \n");
Raymond Knopp's avatar
Raymond Knopp committed
1837
  
1838
  if (!(get_softmodem_params()->emulate_rf)) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1839 1840 1841 1842 1843
    if (ru->stop_rf != NULL) {
      if (ru->stop_rf(ru) != 0)
        LOG_E(HW,"Could not stop the RF device\n");
      else LOG_I(PHY,"RU %d rf device stopped\n",ru->idx);
    }
1844
  }
Raymond Knopp's avatar
Raymond Knopp committed
1845
  
Raymond Knopp's avatar
Raymond Knopp committed
1846
  return NULL;
1847

Raymond Knopp's avatar
Raymond Knopp committed
1848 1849 1850 1851 1852
}


// This thread run the initial synchronization like a UE
void *ru_thread_synch(void *arg) {
1853
  RU_t *ru = (RU_t *)arg;
Raymond Knopp's avatar
Raymond Knopp committed
1854
  LTE_DL_FRAME_PARMS *fp=&ru->frame_parms;
1855 1856
  int64_t peak_val;
  int64_t avg;
Eurecom's avatar
Eurecom committed
1857 1858
  static int ru_thread_synch_status=0;
  int cnt=0;
Raymond Knopp's avatar
Raymond Knopp committed
1859 1860 1861 1862

  thread_top_init("ru_thread_synch",0,5000000,10000000,10000000);
  wait_sync("ru_thread_synch");
  // initialize variables for PSS detection
1863
  ru_sync_time_init(ru);
Raymond Knopp's avatar
Raymond Knopp committed
1864 1865 1866

  while (!oai_exit) {
    // wait to be woken up
1867
    if (wait_on_condition(&ru->proc.mutex_synch,&ru->proc.cond_synch,&ru->proc.instance_cnt_synch,"ru_thread_synch")<0) break;
Raymond Knopp's avatar
Raymond Knopp committed
1868 1869

    // if we're not in synch, then run initial synch
1870
    if (ru->in_synch == 0) {
Raymond Knopp's avatar
Raymond Knopp committed
1871 1872
      // run intial synch like UE
      LOG_I(PHY,"Running initial synchronization\n");
1873
      ru->rx_offset = ru_sync_time(ru,
Raymond Knopp's avatar
Raymond Knopp committed
1874
				   &peak_val,
1875
				   &avg);
1876
      LOG_I(PHY,"RU synch cnt %d: %d, val %llu (%d dB,%d dB)\n",cnt,ru->rx_offset,(unsigned long long)peak_val,dB_fixed64(peak_val),dB_fixed64(avg));
Eurecom's avatar
Eurecom committed
1877
      cnt++;
1878 1879
      //if (/*ru->rx_offset >= 0*/dB_fixed(peak_val)>=85 && cnt>10) {
      if (ru->rx_offset >= 0 && avg>0 && dB_fixed(peak_val/avg)>=15 && cnt>10) {
1880
	LOG_I(PHY,"Estimated peak_val %d dB, avg %d => timing offset %llu\n",dB_fixed(peak_val),dB_fixed(avg),(unsigned long long int)ru->rx_offset);
khadraou's avatar
khadraou committed
1881
	ru->in_synch = 1;
1882
/*
1883
        LOG_M("ru_sync_rx.m","rurx",&ru->common.rxdata[0][0],LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*fp->samples_per_tti,1,1);
1884 1885
        LOG_M("ru_sync_corr.m","sync_corr",ru->dmrs_corr,LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*fp->samples_per_tti,1,6);
        LOG_M("ru_dmrs.m","rudmrs",&ru->dmrssync[0],fp->ofdm_symbol_size,1,1);
1886 1887
  */      
//exit(-1);
1888
      } // sync_pos > 0
1889 1890 1891 1892
      else //AssertFatal(cnt<1000,"Cannot find synch reference\n");
          { 
              if (cnt>200) {
                 LOG_M("ru_sync_rx.m","rurx",&ru->common.rxdata[0][0],LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*fp->samples_per_tti,1,1);
1893 1894 1895
                 LOG_M("ru_sync_corr.m","sync_corr",ru->dmrs_corr,LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*fp->samples_per_tti,1,6);
                 LOG_M("ru_dmrs.m","rudmrs",&ru->dmrssync[0],fp->ofdm_symbol_size,1,1);

1896 1897
                 exit(-1);
              }
1898
          }
Eurecom's avatar
Eurecom committed
1899
    } // ru->in_synch==0
Raymond Knopp's avatar
Raymond Knopp committed
1900 1901 1902
    if (release_thread(&ru->proc.mutex_synch,&ru->proc.instance_cnt_synch,"ru_synch_thread") < 0) break;
  } // oai_exit

1903
  ru_sync_time_free(ru);
Raymond Knopp's avatar
Raymond Knopp committed
1904

1905 1906
  ru_thread_synch_status = 0;
  return &ru_thread_synch_status;
Raymond Knopp's avatar
Raymond Knopp committed
1907 1908
}

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1909
#if defined(PRE_SCD_THREAD)
1910 1911 1912 1913 1914 1915 1916 1917 1918
void *pre_scd_thread( void *param ) {
  static int              eNB_pre_scd_status;
  protocol_ctxt_t         ctxt;
  int                     frame;
  int                     subframe;
  int                     min_rb_unit[MAX_NUM_CCs];
  int                     CC_id;
  int                     Mod_id;
  RU_t               *ru      = (RU_t *)param;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1919
  int                     ret;
1920 1921

  // L2-emulator can work only one eNB
frtabu's avatar
frtabu committed
1922
  if( NFAPI_MODE==NFAPI_MODE_VNF)
1923 1924 1925 1926 1927 1928 1929
    Mod_id = 0;
  else
    Mod_id = ru->eNB_list[0]->Mod_id;

  frame = 0;
  subframe = 4;
  thread_top_init("pre_scd_thread",0,870000,1000000,1000000);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1930

1931 1932 1933 1934
  while (!oai_exit) {
    if(oai_exit) {
      break;
    }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1935

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1936
    AssertFatal((ret=pthread_mutex_lock(&ru->proc.mutex_pre_scd ))==0,"mutex_lock returns %d\n",ret);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1937

1938 1939 1940
    if (ru->proc.instance_pre_scd < 0) {
      pthread_cond_wait(&ru->proc.cond_pre_scd, &ru->proc.mutex_pre_scd);
    }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1941

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1942
    AssertFatal((ret=pthread_mutex_unlock(&ru->proc.mutex_pre_scd))==0,"mutex_unlock returns %d\n",ret);
1943 1944 1945 1946 1947 1948 1949
    PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, Mod_id, ENB_FLAG_YES,
                                   NOT_A_RNTI, frame, subframe,Mod_id);
    pdcp_run(&ctxt);

    for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
      rrc_rx_tx(&ctxt, CC_id);
      min_rb_unit[CC_id] = get_min_rb_unit(Mod_id, CC_id);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1950
    }
1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961

    pre_scd_nb_rbs_required(Mod_id, frame, subframe,min_rb_unit,pre_nb_rbs_required[new_dlsch_ue_select_tbl_in_use]);

    if (subframe==9) {
      subframe=0;
      frame++;
      frame&=1023;
    } else {
      subframe++;
    }

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1962
    AssertFatal((ret=pthread_mutex_lock(&ru->proc.mutex_pre_scd ))==0,"mutex_lock returns %d\n",ret);
1963
    ru->proc.instance_pre_scd--;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1964
    AssertFatal((ret=pthread_mutex_unlock(&ru->proc.mutex_pre_scd))==0,"mutex_unlock returns %d\n",ret);
1965 1966 1967 1968
  }

  eNB_pre_scd_status = 0;
  return &eNB_pre_scd_status;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1969 1970 1971 1972 1973 1974
}
#endif

#ifdef PHY_TX_THREAD
/*!
 * \brief The phy tx thread of eNB.
1975
 * \param param is a \ref L1_proc_t structure which contains the info what to process.
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1976 1977
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
1978
static void *eNB_thread_phy_tx( void *param ) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1979
  static int eNB_thread_phy_tx_status;
1980
  RU_t *ru      = (RU_t *)param;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1981 1982
  RU_proc_t *proc = &ru->proc;
  PHY_VARS_eNB **eNB_list = ru->eNB_list;
1983
  L1_rxtx_proc_t L1_proc;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1984 1985
  // set default return value
  eNB_thread_phy_tx_status = 0;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1986
  int ret;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1987 1988 1989 1990 1991 1992 1993 1994
  thread_top_init("eNB_thread_phy_tx",1,500000L,1000000L,20000000L);

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

    if (wait_on_condition(&proc->mutex_phy_tx,&proc->cond_phy_tx,&proc->instance_cnt_phy_tx,"eNB_phy_tx_thread") < 0) break;

    LOG_D(PHY,"Running eNB phy tx procedures\n");
1995

1996 1997 1998 1999 2000
    AssertFatal(ru->num_eNB == 1, "handle multiple L1 case\n");
    L1_proc.subframe_tx = proc->subframe_phy_tx;
    L1_proc.frame_tx = proc->frame_phy_tx;
    phy_procedures_eNB_TX(eNB_list[0], &L1_proc, 1);
    phy_tx_txdataF_end = 1;
2001

Wang Tsu-Han's avatar
Wang Tsu-Han committed
2002
    AssertFatal((ret=pthread_mutex_lock(&ru->proc.mutex_rf_tx))==0,"[RU] ERROR pthread_mutex_lock for rf tx thread (IC %d)\n", ru->proc.instance_cnt_rf_tx);
2003

2004 2005 2006 2007 2008 2009 2010 2011 2012 2013
    if (ru->proc.instance_cnt_rf_tx==-1) {
      ++ru->proc.instance_cnt_rf_tx;
      ru->proc.frame_tx = proc->frame_phy_tx;
      ru->proc.subframe_tx = proc->subframe_phy_tx;
      ru->proc.timestamp_tx = proc->timestamp_phy_tx;
      // the thread can now be woken up
      AssertFatal(pthread_cond_signal(&ru->proc.cond_rf_tx) == 0, "ERROR pthread_cond_signal for rf_tx thread\n");
    } else {
      LOG_E(PHY,"rf tx thread busy, skipping\n");
      late_control=STATE_BURST_TERMINATE;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2014
    }
2015

Wang Tsu-Han's avatar
Wang Tsu-Han committed
2016
    AssertFatal((ret=pthread_mutex_unlock( &ru->proc.mutex_rf_tx ))==0,"mutex_unlock returns %d\n",ret);
2017

Wang Tsu-Han's avatar
Wang Tsu-Han committed
2018
    if (release_thread(&proc->mutex_phy_tx,&proc->instance_cnt_phy_tx,"eNB_thread_phy_tx") < 0) break;
2019

Wang Tsu-Han's avatar
Wang Tsu-Han committed
2020 2021 2022 2023 2024 2025 2026 2027 2028
    phy_tx_end = 1;
  }

  LOG_I(PHY, "Exiting eNB thread PHY TX\n");
  eNB_thread_phy_tx_status = 0;
  return &eNB_thread_phy_tx_status;
}


2029
static void *rf_tx( void *param ) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2030
  static int rf_tx_status;
2031
  RU_t *ru      = (RU_t *)param;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2032 2033 2034 2035 2036
  RU_proc_t *proc = &ru->proc;
  // set default return value
  rf_tx_status = 0;
  thread_top_init("rf_tx",1,500000L,1000000L,20000000L);

2037
  while (!oai_exit) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2038 2039 2040 2041 2042
    if (oai_exit) break;

    if (wait_on_condition(&proc->mutex_rf_tx,&proc->cond_rf_tx,&proc->instance_cnt_rf_tx,"rf_tx_thread") < 0) break;

    LOG_D(PHY,"Running eNB rf tx procedures\n");
2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056

    if(ru->num_eNB == 1) {
      // do TX front-end processing if needed (precoding and/or IDFTs)
      if (ru->feptx_prec) ru->feptx_prec(ru);

      // do OFDM if needed
      if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru);

      if(!emulate_rf) {
        // do outgoing fronthaul (south) if needed
        if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru);

        if (ru->fh_north_out) ru->fh_north_out(ru);
      }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2057
    }
2058

Wang Tsu-Han's avatar
Wang Tsu-Han committed
2059
    if (release_thread(&proc->mutex_rf_tx,&proc->instance_cnt_rf_tx,"rf_tx") < 0) break;
2060 2061

    if(proc->instance_cnt_rf_tx >= 0) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072
      late_control=STATE_BURST_TERMINATE;
      LOG_E(PHY,"detect rf tx busy change mode TX failsafe\n");
    }
  }

  LOG_I(PHY, "Exiting rf TX\n");
  rf_tx_status = 0;
  return &rf_tx_status;
}
#endif

Raymond Knopp's avatar
Raymond Knopp committed
2073

2074

2075 2076 2077 2078 2079 2080 2081 2082
int start_if(struct RU_t_s *ru,struct PHY_VARS_eNB_s *eNB) {
  return(ru->ifdevice.trx_start_func(&ru->ifdevice));
}

int start_rf(RU_t *ru) {
  return(ru->rfdevice.trx_start_func(&ru->rfdevice));
}

2083
int stop_rf(RU_t *ru) {
2084 2085 2086 2087
  ru->rfdevice.trx_end_func(&ru->rfdevice);
  return 0;
}

2088
extern void fep_full(RU_t *ru);
2089
extern void ru_fep_full_2thread(RU_t *ru);
2090
extern void feptx_ofdm(RU_t *ru);
2091
extern void feptx_ofdm_2thread(RU_t *ru);
2092
extern void feptx_prec(RU_t *ru);
2093 2094
extern void init_fep_thread(RU_t *ru,pthread_attr_t *attr);
extern void init_feptx_thread(RU_t *ru,pthread_attr_t *attr);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2095 2096
extern void kill_fep_thread(RU_t *ru);
extern void kill_feptx_thread(RU_t *ru);
2097

2098 2099 2100
extern void configure_ru(int idx,
		  void *arg);

2101 2102
void reset_proc(RU_t *ru) {

2103 2104
  int i=0;
  RU_proc_t *proc;
2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117

  AssertFatal(ru != NULL, "ru is null\n");
  proc = &ru->proc;

  proc->ru = ru;
  proc->first_rx                 = 1;
  proc->first_tx                 = 1;
  proc->frame_offset             = 0;
  proc->frame_tx_unwrap          = 0;

  for (i=0;i<10;i++) proc->symbol_mask[i]=0;
}

2118 2119
extern void* ru_thread_control( void* param );

2120
void init_RU_proc(RU_t *ru) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2121
  int i=0,ret;
2122
  RU_proc_t *proc;
2123
  pthread_attr_t *attr_FH=NULL,*attr_FH1=NULL,*attr_prach=NULL,*attr_asynch=NULL,*attr_synch=NULL,*attr_emulateRF=NULL, *attr_ctrl=NULL;
2124
  //pthread_attr_t *attr_fep=NULL;
2125
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
2126 2127
  pthread_attr_t *attr_prach_br=NULL;
#endif
2128 2129

#ifndef OCP_FRAMEWORK
2130
  LOG_I(PHY,"Initializing RU proc %d (%s,%s),\n",ru->idx,eNB_functions[ru->function],eNB_timing[ru->if_timing]);
2131 2132
#endif
  proc = &ru->proc;
2133
  memset((void *)proc,0,sizeof(RU_proc_t));
2134 2135
  proc->ru = ru;
  proc->instance_cnt_prach       = -1;
2136
  proc->instance_cnt_synch       = -1;
2137
  proc->instance_cnt_FH          = -1;
2138
  proc->instance_cnt_FH1         = -1;
2139
  proc->instance_cnt_emulateRF   = -1;
2140
  proc->instance_cnt_asynch_rxtx = -1;
2141

khadraou's avatar
khadraou committed
2142
  proc->instance_cnt_ru 	 = -1;
2143

2144
  proc->instance_cnt_eNBs        = -1;
2145

2146 2147 2148 2149
  proc->first_rx                 = 1;
  proc->first_tx                 = 1;
  proc->frame_offset             = 0;
  proc->num_slaves               = 0;
2150 2151
  proc->frame_tx_unwrap          = 0;

2152 2153
  for (i=0; i<10; i++) proc->symbol_mask[i]=0;

2154 2155 2156 2157
  pthread_mutex_init( &proc->mutex_prach, NULL);
  pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL);
  pthread_mutex_init( &proc->mutex_synch,NULL);
  pthread_mutex_init( &proc->mutex_FH,NULL);
2158
  pthread_mutex_init( &proc->mutex_FH1,NULL);
2159
  pthread_mutex_init( &proc->mutex_emulateRF,NULL);
2160
  pthread_mutex_init( &proc->mutex_eNBs, NULL);
2161
  pthread_mutex_init( &proc->mutex_ru,NULL);
2162

2163 2164
  pthread_cond_init( &proc->cond_prach, NULL);
  pthread_cond_init( &proc->cond_FH, NULL);
2165
  pthread_cond_init( &proc->cond_FH1, NULL);
2166
  pthread_cond_init( &proc->cond_emulateRF, NULL);
2167 2168
  pthread_cond_init( &proc->cond_asynch_rxtx, NULL);
  pthread_cond_init( &proc->cond_synch,NULL);
2169
  pthread_cond_init( &proc->cond_eNBs, NULL);
2170
  pthread_cond_init( &proc->cond_ru_thread,NULL);
2171

2172
  pthread_attr_init( &proc->attr_FH);
2173
  pthread_attr_init( &proc->attr_FH1);
2174
  pthread_attr_init( &proc->attr_emulateRF);
2175 2176 2177 2178
  pthread_attr_init( &proc->attr_prach);
  pthread_attr_init( &proc->attr_synch);
  pthread_attr_init( &proc->attr_asynch_rxtx);
  pthread_attr_init( &proc->attr_fep);
2179
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
2180 2181 2182 2183
  proc->instance_cnt_prach_br       = -1;
  pthread_mutex_init( &proc->mutex_prach_br, NULL);
  pthread_cond_init( &proc->cond_prach_br, NULL);
  pthread_attr_init( &proc->attr_prach_br);
2184
#endif
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2185 2186 2187 2188 2189 2190 2191 2192
#ifdef PHY_TX_THREAD
  proc->instance_cnt_phy_tx       = -1;
  pthread_mutex_init( &proc->mutex_phy_tx, NULL);
  pthread_cond_init( &proc->cond_phy_tx, NULL);
  proc->instance_cnt_rf_tx       = -1;
  pthread_mutex_init( &proc->mutex_rf_tx, NULL);
  pthread_cond_init( &proc->cond_rf_tx, NULL);
#endif
2193
#ifndef DEADLINE_SCHEDULER
2194
  attr_FH        = &proc->attr_FH;
2195
  attr_FH1       = &proc->attr_FH1;
2196 2197 2198
  attr_prach     = &proc->attr_prach;
  attr_synch     = &proc->attr_synch;
  attr_asynch    = &proc->attr_asynch_rxtx;
2199
  attr_emulateRF = &proc->attr_emulateRF;
2200
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
2201 2202
  attr_prach_br  = &proc->attr_prach_br;
#endif
2203
#endif
2204
  if (ru->function!=eNodeB_3GPP) pthread_create( &proc->pthread_ctrl, attr_ctrl, ru_thread_control, (void*)ru );
2205
  
Raymond Knopp's avatar
Raymond Knopp committed
2206

2207
  pthread_create( &proc->pthread_FH, attr_FH, ru_thread, (void*)ru );
2208

Wang Tsu-Han's avatar
Wang Tsu-Han committed
2209
#if defined(PRE_SCD_THREAD)
2210 2211 2212 2213 2214
  proc->instance_pre_scd = -1;
  pthread_mutex_init( &proc->mutex_pre_scd, NULL);
  pthread_cond_init( &proc->cond_pre_scd, NULL);
  pthread_create(&proc->pthread_pre_scd, NULL, pre_scd_thread, (void *)ru);
  pthread_setname_np(proc->pthread_pre_scd, "pre_scd_thread");
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2215 2216
#endif
#ifdef PHY_TX_THREAD
2217 2218 2219
  pthread_create( &proc->pthread_phy_tx, NULL, eNB_thread_phy_tx, (void *)ru );
  pthread_setname_np( proc->pthread_phy_tx, "phy_tx_thread" );
  pthread_create( &proc->pthread_rf_tx, NULL, rf_tx, (void *)ru );
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2220 2221
#endif

2222
  if(get_softmodem_params()->emulate_rf)
2223
    pthread_create( &proc->pthread_emulateRF, attr_emulateRF, emulatedRF_thread, (void *)proc );
2224

2225
  if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT)
2226
    pthread_create( &proc->pthread_FH1, attr_FH1, ru_thread_tx, (void *)ru );
Raymond Knopp's avatar
Raymond Knopp committed
2227

2228

2229
  if (ru->function == NGFI_RRU_IF4p5) {
2230 2231 2232
    pthread_create( &proc->pthread_prach, attr_prach, ru_thread_prach, (void *)ru );
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
    pthread_create( &proc->pthread_prach_br, attr_prach_br, ru_thread_prach_br, (void *)ru );
2233
#endif
2234 2235 2236

    if (ru->is_slave == 1) pthread_create( &proc->pthread_synch, attr_synch, ru_thread_synch, (void *)ru);

2237 2238
    if ((ru->if_timing == synch_to_other) ||
	(ru->function == NGFI_RRU_IF5) ||
2239 2240 2241
	(ru->function == NGFI_RRU_IF4p5)) {
        LOG_I(PHY,"Starting ru_thread_asynch_rxtx, ru->is_slave %d, ru->generate_dmrs_sync %d\n",
              ru->is_slave,ru->generate_dmrs_sync);
magounak's avatar
magounak committed
2242 2243 2244
	//generate_ul_ref_sigs();
        //ru->dmrssync = (int16_t*)malloc16_clear(ru->frame_parms.ofdm_symbol_size*2*sizeof(int16_t)); 
        pthread_create( &proc->pthread_asynch_rxtx, attr_asynch, ru_thread_asynch_rxtx, (void*)ru );
2245
    }
2246 2247
    
    
Raymond Knopp's avatar
Raymond Knopp committed
2248
  }
2249
  else if (ru->function == eNodeB_3GPP && ru->if_south == LOCAL_RF) { // DJP - need something else to distinguish between monolithic and PNF
Cedric Roux's avatar
Cedric Roux committed
2250
    LOG_I(PHY,"%s() DJP - added creation of pthread_prach\n", __FUNCTION__);
2251
    pthread_create( &proc->pthread_prach, attr_prach, ru_thread_prach, (void*)ru );
2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264
    ru->state=RU_RUN;
    fill_rf_config(ru,ru->rf_config_file);
    init_frame_parms(&ru->frame_parms,1);
    ru->frame_parms.nb_antennas_rx = ru->nb_rx;
    phy_init_RU(ru);


    openair0_device_load(&ru->rfdevice,&ru->openair0_cfg);

   if (setup_RU_buffers(ru)!=0) {
      printf("Exiting, cannot initialize RU Buffers\n");
      exit(-1);
   }
2265
  }
2266

2267 2268
  if (get_thread_worker_conf() == WORKER_ENABLE) {
    init_fep_thread(ru,NULL);
2269
    init_feptx_thread(ru,NULL);
2270
  } 
2271
  if (opp_enabled == 1) pthread_create(&ru->ru_stats_thread,NULL,ru_stats_thread,(void*)ru); 
2272
 
2273

2274 2275
  if (ru->function == eNodeB_3GPP) {
    usleep(10000);
2276
    LOG_I(PHY, "Signaling main thread that RU %d (is_slave %d,send_dmrs %d) is ready in state %s\n",ru->idx,ru->is_slave,ru->generate_dmrs_sync,ru_states[ru->state]);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2277
    AssertFatal((ret=pthread_mutex_lock(&RC.ru_mutex))==0,"mutex_lock returns %d\n",ret);
2278 2279
    RC.ru_mask &= ~(1<<ru->idx);
    pthread_cond_signal(&RC.ru_cond);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2280
    AssertFatal((ret=pthread_mutex_unlock(&RC.ru_mutex))==0,"mutex_unlock returns %d\n",ret);
2281
  }
2282 2283
}

2284
void kill_RU_proc(RU_t *ru) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2285
  int ret;
Robert Schmidt's avatar
Robert Schmidt committed
2286
  RU_proc_t *proc = &ru->proc;
Robert Schmidt's avatar
Robert Schmidt committed
2287
#if defined(PRE_SCD_THREAD)
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2288
  AssertFatal((ret=pthread_mutex_lock(&proc->mutex_pre_scd))==0,"mutex_lock returns %d\n",ret);
Robert Schmidt's avatar
Robert Schmidt committed
2289 2290
  ru->proc.instance_pre_scd = 0;
  pthread_cond_signal(&proc->cond_pre_scd);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2291
  AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_pre_scd))==0,"mutex_unlock returns %d\n",ret);
Robert Schmidt's avatar
Robert Schmidt committed
2292 2293 2294 2295 2296
  pthread_join(proc->pthread_pre_scd, NULL);
  pthread_mutex_destroy(&proc->mutex_pre_scd);
  pthread_cond_destroy(&proc->cond_pre_scd);
#endif
#ifdef PHY_TX_THREAD
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2297
  AssertFatal((ret=pthread_mutex_lock(&proc->mutex_phy_tx))==0,"mutex_lock returns %d\n",ret);
Robert Schmidt's avatar
Robert Schmidt committed
2298 2299
  proc->instance_cnt_phy_tx = 0;
  pthread_cond_signal(&proc->cond_phy_tx);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2300
  AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_phy_tx))==0,"mutex_unlock returns %d\n",ret);
Robert Schmidt's avatar
Robert Schmidt committed
2301 2302 2303
  pthread_join(ru->proc.pthread_phy_tx, NULL);
  pthread_mutex_destroy( &proc->mutex_phy_tx);
  pthread_cond_destroy( &proc->cond_phy_tx);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2304
  AssertFatal((ret=pthread_mutex_lock(&proc->mutex_rf_tx))==0,"mutex_lock returns %d\n",ret);
Robert Schmidt's avatar
Robert Schmidt committed
2305 2306
  proc->instance_cnt_rf_tx = 0;
  pthread_cond_signal(&proc->cond_rf_tx);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2307
  AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_rf_tx))==0,"mutex_unlock returns %d\n",ret);
Robert Schmidt's avatar
Robert Schmidt committed
2308 2309 2310 2311 2312
  pthread_join(proc->pthread_rf_tx, NULL);
  pthread_mutex_destroy( &proc->mutex_rf_tx);
  pthread_cond_destroy( &proc->cond_rf_tx);
#endif

2313
  if (get_thread_worker_conf() == WORKER_ENABLE) {
2314 2315 2316 2317
    LOG_D(PHY, "killing FEP thread\n");
    kill_fep_thread(ru);
    LOG_D(PHY, "killing FEP TX thread\n");
    kill_feptx_thread(ru);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2318 2319
  }

Wang Tsu-Han's avatar
Wang Tsu-Han committed
2320
  AssertFatal((ret=pthread_mutex_lock(&proc->mutex_FH))==0,"mutex_lock returns %d\n",ret);
Robert Schmidt's avatar
Robert Schmidt committed
2321 2322
  proc->instance_cnt_FH = 0;
  pthread_cond_signal(&proc->cond_FH);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2323 2324
  AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_FH))==0,"mutex_unlock returns %d\n",ret);
  AssertFatal((ret=pthread_mutex_lock(&proc->mutex_FH1))==0,"mutex_lock returns %d\n",ret);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2325 2326
  proc->instance_cnt_FH1 = 0;
  pthread_cond_signal(&proc->cond_FH1);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2327 2328
  AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_FH1))==0,"mutex_unlock returns %d\n",ret);
  AssertFatal((ret=pthread_mutex_lock(&proc->mutex_prach))==0,"mutex_lock returns %d\n",ret);
Robert Schmidt's avatar
Robert Schmidt committed
2329 2330
  proc->instance_cnt_prach = 0;
  pthread_cond_signal(&proc->cond_prach);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2331
  AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_prach))==0,"mutex_unlock returns %d\n",ret);
2332
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2333
  AssertFatal((ret=pthread_mutex_lock(&proc->mutex_prach_br))==0,"mutex_lock returns %d\n",ret);
Robert Schmidt's avatar
Robert Schmidt committed
2334 2335
  proc->instance_cnt_prach_br = 0;
  pthread_cond_signal(&proc->cond_prach_br);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2336
  AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_prach_br))==0,"mutex_unlock returns %d\n",ret);
Robert Schmidt's avatar
Robert Schmidt committed
2337
#endif
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2338
  AssertFatal((ret=pthread_mutex_lock(&proc->mutex_synch))==0,"mutex_lock returns %d\n",ret);
Robert Schmidt's avatar
Robert Schmidt committed
2339 2340
  proc->instance_cnt_synch = 0;
  pthread_cond_signal(&proc->cond_synch);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2341 2342
  AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_synch))==0,"mutex_unlock returns %d\n",ret);
  AssertFatal((ret=pthread_mutex_lock(&proc->mutex_eNBs))==0,"mutex_lock returns %d\n",ret);
Robert Schmidt's avatar
Robert Schmidt committed
2343 2344 2345 2346
  proc->instance_cnt_eNBs = 1;
  // cond_eNBs is used by both ru_thread and ru_thread_tx, so we need to send
  // a broadcast to wake up both threads
  pthread_cond_broadcast(&proc->cond_eNBs);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2347 2348
  AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_eNBs))==0,"mutex_unlock returns %d\n",ret);
  AssertFatal((ret=pthread_mutex_lock(&proc->mutex_asynch_rxtx))==0,"mutex_lock returns %d\n",ret);
Robert Schmidt's avatar
Robert Schmidt committed
2349 2350
  proc->instance_cnt_asynch_rxtx = 0;
  pthread_cond_signal(&proc->cond_asynch_rxtx);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2351
  AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_asynch_rxtx))==0,"mutex_unlock returns %d\n",ret);
Robert Schmidt's avatar
Robert Schmidt committed
2352
  LOG_D(PHY, "Joining pthread_FH\n");
Robert Schmidt's avatar
Robert Schmidt committed
2353
  pthread_join(proc->pthread_FH, NULL);
2354

2355
  if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) {
Robert Schmidt's avatar
Robert Schmidt committed
2356 2357 2358
    LOG_D(PHY, "Joining pthread_FHTX\n");
    pthread_join(proc->pthread_FH1, NULL);
  }
2359

Robert Schmidt's avatar
Robert Schmidt committed
2360 2361 2362
  if (ru->function == NGFI_RRU_IF4p5) {
    LOG_D(PHY, "Joining pthread_prach\n");
    pthread_join(proc->pthread_prach, NULL);
2363
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
Robert Schmidt's avatar
Robert Schmidt committed
2364 2365 2366
    LOG_D(PHY, "Joining pthread_prach_br\n");
    pthread_join(proc->pthread_prach_br, NULL);
#endif
2367

Robert Schmidt's avatar
Robert Schmidt committed
2368 2369 2370 2371
    if (ru->is_slave) {
      LOG_D(PHY, "Joining pthread_\n");
      pthread_join(proc->pthread_synch, NULL);
    }
2372

Robert Schmidt's avatar
Robert Schmidt committed
2373 2374 2375 2376 2377 2378 2379
    if ((ru->if_timing == synch_to_other) ||
        (ru->function == NGFI_RRU_IF5) ||
        (ru->function == NGFI_RRU_IF4p5)) {
      LOG_D(PHY, "Joining pthread_asynch_rxtx\n");
      pthread_join(proc->pthread_asynch_rxtx, NULL);
    }
  }
2380

Robert Schmidt's avatar
Robert Schmidt committed
2381 2382 2383 2384 2385 2386 2387 2388 2389
  if (opp_enabled) {
    LOG_D(PHY, "Joining ru_stats_thread\n");
    pthread_join(ru->ru_stats_thread, NULL);
  }

  pthread_mutex_destroy(&proc->mutex_prach);
  pthread_mutex_destroy(&proc->mutex_asynch_rxtx);
  pthread_mutex_destroy(&proc->mutex_synch);
  pthread_mutex_destroy(&proc->mutex_FH);
2390
  pthread_mutex_destroy(&proc->mutex_FH1);
Robert Schmidt's avatar
Robert Schmidt committed
2391 2392 2393
  pthread_mutex_destroy(&proc->mutex_eNBs);
  pthread_cond_destroy(&proc->cond_prach);
  pthread_cond_destroy(&proc->cond_FH);
2394
  pthread_cond_destroy(&proc->cond_FH1);
Robert Schmidt's avatar
Robert Schmidt committed
2395 2396 2397 2398
  pthread_cond_destroy(&proc->cond_asynch_rxtx);
  pthread_cond_destroy(&proc->cond_synch);
  pthread_cond_destroy(&proc->cond_eNBs);
  pthread_attr_destroy(&proc->attr_FH);
2399
  pthread_attr_destroy(&proc->attr_FH1);
Robert Schmidt's avatar
Robert Schmidt committed
2400 2401 2402 2403
  pthread_attr_destroy(&proc->attr_prach);
  pthread_attr_destroy(&proc->attr_synch);
  pthread_attr_destroy(&proc->attr_asynch_rxtx);
  pthread_attr_destroy(&proc->attr_fep);
2404
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
Robert Schmidt's avatar
Robert Schmidt committed
2405 2406 2407 2408 2409
  pthread_mutex_destroy(&proc->mutex_prach_br);
  pthread_cond_destroy(&proc->cond_prach_br);
  pthread_attr_destroy(&proc->attr_prach_br);
#endif
}
Raymond Knopp's avatar
Raymond Knopp committed
2410

2411 2412 2413 2414 2415 2416 2417
void init_precoding_weights(PHY_VARS_eNB *eNB) {
  int layer,ru_id,aa,re,ue,tb;
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
  RU_t *ru;
  LTE_eNB_DLSCH_t *dlsch;

  // init precoding weigths
2418 2419
  for (ue=0; ue<NUMBER_OF_UE_MAX; ue++) {
    for (tb=0; tb<2; tb++) {
2420
      dlsch = eNB->dlsch[ue][tb];
2421

2422
      for (layer=0; layer<4; layer++) {
2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438
        int nb_tx=0;

        for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
          ru = RC.ru[ru_id];
          nb_tx+=ru->nb_tx;
        }

        dlsch->ue_spec_bf_weights[layer] = (int32_t **)malloc16(nb_tx*sizeof(int32_t *));

        for (aa=0; aa<nb_tx; aa++) {
          dlsch->ue_spec_bf_weights[layer][aa] = (int32_t *)malloc16(fp->ofdm_symbol_size*sizeof(int32_t));

          for (re=0; re<fp->ofdm_symbol_size; re++) {
            dlsch->ue_spec_bf_weights[layer][aa][re] = 0x00007fff;
          }
        }
2439 2440 2441 2442 2443
      }
    }
  }
}

2444
void set_function_spec_param(RU_t *ru) {
2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467
  int ret;

  switch (ru->if_south) {
  case LOCAL_RF:   // this is an RU with integrated RF (RRU, eNB)
    if (ru->function ==  NGFI_RRU_IF5) {                 // IF5 RRU
      ru->do_prach              = 0;                      // no prach processing in RU
      ru->fh_north_in           = NULL;                   // no shynchronous incoming fronthaul from north
      ru->fh_north_out          = fh_if5_north_out;       // need only to do send_IF5  reception
      ru->fh_south_out          = tx_rf;                  // send output to RF
      ru->fh_north_asynch_in    = fh_if5_north_asynch_in; // TX packets come asynchronously
      ru->feprx                 = NULL;                   // nothing (this is a time-domain signal)
      ru->feptx_ofdm            = NULL;                   // nothing (this is a time-domain signal)
      ru->feptx_prec            = NULL;                   // nothing (this is a time-domain signal)
      ru->start_if              = start_if;               // need to start the if interface for if5
      ru->ifdevice.host_type    = RRU_HOST;
      ru->rfdevice.host_type    = RRU_HOST;
      ru->ifdevice.eth_params   = &ru->eth_params;
      reset_meas(&ru->rx_fhaul);
      reset_meas(&ru->tx_fhaul);
      reset_meas(&ru->compression);
      reset_meas(&ru->transport);
      ret = openair0_transport_load(&ru->ifdevice,&ru->openair0_cfg,&ru->eth_params);
      printf("openair0_transport_init returns %d for ru_id %d\n", ret, ru->idx);
2468
      
2469
      if (ret<0) {
2470 2471
	printf("Exiting, cannot initialize transport protocol\n");
	exit(-1);
2472
      }
2473
    } else if (ru->function == NGFI_RRU_IF4p5) {
2474 2475 2476 2477 2478
      ru->do_prach              = 1;                        // do part of prach processing in RU
      ru->fh_north_in           = NULL;                     // no synchronous incoming fronthaul from north
      ru->fh_north_out          = fh_if4p5_north_out;       // send_IF4p5 on reception
      ru->fh_south_out          = tx_rf;                    // send output to RF
      ru->fh_north_asynch_in    = fh_if4p5_north_asynch_in; // TX packets come asynchronously
2479 2480
      ru->feprx                 = (get_thread_worker_conf() == WORKER_DISABLE) ? fep_full :ru_fep_full_2thread;                 // RX DFTs
      ru->feptx_ofdm            = (get_thread_worker_conf() == WORKER_DISABLE) ? feptx_ofdm : feptx_ofdm_2thread;               // this is fep with idft only (no precoding in RRU)
2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491
      ru->feptx_prec            = NULL;
      ru->start_if              = start_if;                 // need to start the if interface for if4p5
      ru->ifdevice.host_type    = RRU_HOST;
      ru->rfdevice.host_type    = RRU_HOST;
      ru->ifdevice.eth_params   = &ru->eth_params;
      reset_meas(&ru->rx_fhaul);
      reset_meas(&ru->tx_fhaul);
      reset_meas(&ru->compression);
      reset_meas(&ru->transport);
      ret = openair0_transport_load(&ru->ifdevice,&ru->openair0_cfg,&ru->eth_params);
      printf("openair0_transport_init returns %d for ru_id %d\n", ret, ru->idx);
2492
      
2493
      if (ret<0) {
2494 2495
	printf("Exiting, cannot initialize transport protocol\n");
	exit(-1);
2496
      }
2497
      
2498
      malloc_IF4p5_buffer(ru);
2499
    } else if (ru->function == eNodeB_3GPP) {
2500
      ru->do_prach             = 0;                       // no prach processing in RU
2501 2502
      ru->feprx                = (get_thread_worker_conf() == WORKER_DISABLE) ? fep_full : ru_fep_full_2thread;                // RX DFTs
      ru->feptx_ofdm           = (get_thread_worker_conf() == WORKER_DISABLE) ? feptx_ofdm : feptx_ofdm_2thread;              // this is fep with idft and precoding
2503 2504 2505 2506 2507 2508
      ru->feptx_prec           = feptx_prec;              // this is fep with idft and precoding
      ru->fh_north_in          = NULL;                    // no incoming fronthaul from north
      ru->fh_north_out         = NULL;                    // no outgoing fronthaul to north
      ru->start_if             = NULL;                    // no if interface
      ru->rfdevice.host_type   = RAU_HOST;
    }
2509
    
2510 2511 2512
    ru->fh_south_in            = rx_rf;                               // local synchronous RF RX
    ru->fh_south_out           = tx_rf;                               // local synchronous RF TX
    ru->start_rf               = start_rf;                            // need to start the local RF interface
2513
    ru->stop_rf                = stop_rf;
2514
    printf("configuring ru_id %d (start_rf %p)\n", ru->idx, start_rf);
Raymond Knopp's avatar
Raymond Knopp committed
2515 2516
    /*
      if (ru->function == eNodeB_3GPP) { // configure RF parameters only for 3GPP eNodeB, we need to get them from RAU otherwise
2517 2518 2519
      fill_rf_config(ru,rf_config_file);
      init_frame_parms(&ru->frame_parms,1);
      phy_init_RU(ru);
Raymond Knopp's avatar
Raymond Knopp committed
2520
      }
2521
      
Raymond Knopp's avatar
Raymond Knopp committed
2522 2523
      ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg);
      if (setup_RU_buffers(ru)!=0) {
2524 2525
      printf("Exiting, cannot initialize RU Buffers\n");
      exit(-1);
Raymond Knopp's avatar
Raymond Knopp committed
2526
      }*/
2527
    break;
2528
    
2529 2530
  case REMOTE_IF5: // the remote unit is IF5 RRU
    ru->do_prach               = 0;
2531
    ru->feprx                  = (get_thread_worker_conf() == WORKER_DISABLE) ? fep_full : fep_full;                   // this is frequency-shift + DFTs
2532
    ru->feptx_prec             = feptx_prec;                 // need to do transmit Precoding + IDFTs
2533
    ru->feptx_ofdm             = (get_thread_worker_conf() == WORKER_DISABLE) ? feptx_ofdm : feptx_ofdm_2thread;                 // need to do transmit Precoding + IDFTs
2534 2535 2536 2537 2538 2539 2540 2541 2542
    
    if (ru->if_timing == synch_to_other) {
      ru->fh_south_in          = fh_slave_south_in;                  // synchronize to master
    } else {
      ru->fh_south_in          = fh_if5_south_in;     // synchronous IF5 reception
      ru->fh_south_out         = fh_if5_south_out;    // synchronous IF5 transmission
      ru->fh_south_asynch_in   = NULL;                // no asynchronous UL
    }
    
2543
    ru->start_rf               = NULL;                 // no local RF
2544
    ru->stop_rf                = NULL;
2545 2546 2547 2548 2549 2550
    ru->start_if               = start_if;             // need to start if interface for IF5
    ru->ifdevice.host_type     = RAU_HOST;
    ru->ifdevice.eth_params    = &ru->eth_params;
    ru->ifdevice.configure_rru = configure_ru;
    ret = openair0_transport_load(&ru->ifdevice,&ru->openair0_cfg,&ru->eth_params);
    printf("openair0_transport_init returns %d for ru_id %d\n", ret, ru->idx);
2551
    
2552 2553 2554 2555
    if (ret<0) {
      printf("Exiting, cannot initialize transport protocol\n");
      exit(-1);
    }
2556
    
2557
    break;
2558
    
2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569
  case REMOTE_IF4p5:
    ru->do_prach               = 0;
    ru->feprx                  = NULL;                // DFTs
    ru->feptx_prec             = feptx_prec;          // Precoding operation
    ru->feptx_ofdm             = NULL;                // no OFDM mod
    ru->fh_south_in            = fh_if4p5_south_in;   // synchronous IF4p5 reception
    ru->fh_south_out           = fh_if4p5_south_out;  // synchronous IF4p5 transmission
    ru->fh_south_asynch_in     = (ru->if_timing == synch_to_other) ? fh_if4p5_south_in : NULL;                // asynchronous UL if synch_to_other
    ru->fh_north_out           = NULL;
    ru->fh_north_asynch_in     = NULL;
    ru->start_rf               = NULL;                // no local RF
2570
    ru->stop_rf                = NULL;
2571 2572 2573 2574 2575 2576
    ru->start_if               = start_if;            // need to start if interface for IF4p5
    ru->ifdevice.host_type     = RAU_HOST;
    ru->ifdevice.eth_params    = &ru->eth_params;
    ru->ifdevice.configure_rru = configure_ru;
    ret = openair0_transport_load(&ru->ifdevice, &ru->openair0_cfg, &ru->eth_params);
    printf("openair0_transport_init returns %d for ru_id %d\n", ret, ru->idx);
2577
    
2578 2579 2580 2581 2582 2583
    if (ret<0) {
      printf("Exiting, cannot initialize transport protocol\n");
      exit(-1);
    }
    malloc_IF4p5_buffer(ru);
    break;
2584
  
2585 2586 2587 2588 2589
  default:
    LOG_E(PHY,"RU with invalid or unknown southbound interface type %d\n",ru->if_south);
    break;
  } // switch on interface type
}
2590
 
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2591
//extern void RCconfig_RU(void);
Raymond Knopp's avatar
Raymond Knopp committed
2592

2593
void init_RU(char *rf_config_file, clock_source_t clock_source,clock_source_t time_source,int send_dmrssync) {
Raymond Knopp's avatar
Raymond Knopp committed
2594 2595
  
  int ru_id;
2596
  RU_t *ru;
2597
  PHY_VARS_eNB *eNB0= (PHY_VARS_eNB *)NULL;
2598 2599 2600 2601 2602 2603
  int i;
  int CC_id;
  // create status mask
  RC.ru_mask = 0;
  pthread_mutex_init(&RC.ru_mutex,NULL);
  pthread_cond_init(&RC.ru_cond,NULL);
2604 2605
  // read in configuration file)
  printf("configuring RU from file\n");
2606
  RCconfig_RU();
2607
  LOG_I(PHY,"number of L1 instances %d, number of RU %d, number of CPU cores %d\n",RC.nb_L1_inst,RC.nb_RU,get_nprocs());
2608

2609
  if (RC.nb_CC != 0)
2610 2611
    for (i=0; i<RC.nb_L1_inst; i++)
      for (CC_id=0; CC_id<RC.nb_CC[i]; CC_id++) RC.eNB[i][CC_id]->num_RU=0;
2612

Cedric Roux's avatar
Cedric Roux committed
2613
  LOG_D(PHY,"Process RUs RC.nb_RU:%d\n",RC.nb_RU);
2614 2615

  for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
Cedric Roux's avatar
Cedric Roux committed
2616
    LOG_D(PHY,"Process RC.ru[%d]\n",ru_id);
2617
    ru               = RC.ru[ru_id];
2618
    ru->rf_config_file = rf_config_file;
2619
    ru->idx          = ru_id;
2620
    ru->ts_offset    = 0;
2621 2622
    if (ru->is_slave == 1) {
       ru->in_synch    = 0;
Raymond Knopp's avatar
Raymond Knopp committed
2623
       ru->generate_dmrs_sync = 0; 	
2624 2625 2626 2627 2628
    }
    else {
       ru->in_synch    = 1;
       ru->generate_dmrs_sync=send_dmrssync;
    }
2629
    ru->cmd	     = EMPTY;
2630
    ru->south_out_cnt= 0;
2631 2632
    // use eNB_list[0] as a reference for RU frame parameters
    // NOTE: multiple CC_id are not handled here yet!
2633 2634
    ru->openair0_cfg.clock_source  = clock_source;
    ru->openair0_cfg.time_source = time_source;
2635 2636 2637 2638 2639
    //ru->generate_dmrs_sync = (ru->is_slave == 0) ? 1 : 0;
    if ((ru->is_slave == 0) && (ru->ota_sync_enable == 1))
      ru->generate_dmrs_sync = 1;
    else
      ru->generate_dmrs_sync = 0;
magounak's avatar
magounak committed
2640
    if (ru->generate_dmrs_sync == 1) {
Raymond Knopp's avatar
Raymond Knopp committed
2641 2642
      generate_ul_ref_sigs();
      ru->dmrssync = (int16_t*)malloc16_clear(ru->frame_parms.ofdm_symbol_size*2*sizeof(int16_t)); 	
magounak's avatar
magounak committed
2643
    }
2644 2645
    ru->wakeup_L1_sleeptime = 2000;
    ru->wakeup_L1_sleep_cnt_max  = 3;
2646 2647
    if (ru->num_eNB > 0) {
      LOG_D(PHY, "%s() RC.ru[%d].num_eNB:%d ru->eNB_list[0]:%p RC.eNB[0][0]:%p rf_config_file:%s\n", __FUNCTION__, ru_id, ru->num_eNB, ru->eNB_list[0], RC.eNB[0][0], ru->rf_config_file);
2648

2649
      if (ru->eNB_list[0] == 0) {
2650 2651 2652
        LOG_E(PHY,"%s() DJP - ru->eNB_list ru->num_eNB are not initialized - so do it manually\n", __FUNCTION__);
        ru->eNB_list[0] = RC.eNB[0][0];
        ru->num_eNB=1;
2653 2654 2655 2656
        //
        // DJP - feptx_prec() / feptx_ofdm() parses the eNB_list (based on num_eNB) and copies the txdata_F to txdata in RU
        //
      } else {
2657
        LOG_E(PHY,"DJP - delete code above this %s:%d\n", __FILE__, __LINE__);
Raymond Knopp's avatar
Raymond Knopp committed
2658
      }
2659
    }
2660

2661
    eNB0             = ru->eNB_list[0];
Cedric Roux's avatar
Cedric Roux committed
2662 2663
    LOG_D(PHY, "RU FUnction:%d ru->if_south:%d\n", ru->function, ru->if_south);
    LOG_D(PHY, "eNB0:%p\n", eNB0);
2664
    if (eNB0)
Raymond Knopp's avatar
Raymond Knopp committed
2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679
      {
	if ((ru->function != NGFI_RRU_IF5) && (ru->function != NGFI_RRU_IF4p5))
	  AssertFatal(eNB0!=NULL,"eNB0 is null!\n");

	if (eNB0) {
	  LOG_I(PHY,"Copying frame parms from eNB %d to ru %d\n",eNB0->Mod_id,ru->idx);
	  memcpy((void*)&ru->frame_parms,(void*)&eNB0->frame_parms,sizeof(LTE_DL_FRAME_PARMS));

	  // attach all RU to all eNBs in its list/
	  LOG_D(PHY,"ru->num_eNB:%d eNB0->num_RU:%d\n", ru->num_eNB, eNB0->num_RU);
	  for (i=0;i<ru->num_eNB;i++) {
	    eNB0 = ru->eNB_list[i];
	    eNB0->RU_list[eNB0->num_RU++] = ru;
	  }
	}
Raymond Knopp's avatar
Raymond Knopp committed
2680
      }
2681
    //    LOG_I(PHY,"Initializing RRU descriptor %d : (%s,%s,%d)\n",ru_id,ru_if_types[ru->if_south],eNB_timing[ru->if_timing],ru->function);
2682
    LOG_I(PHY,"Initializing RRU descriptor %d : (%s,%s,%d)\n",ru_id,ru_if_types[ru->if_south],eNB_timing[ru->if_timing],ru->function);
2683
    set_function_spec_param(ru);
2684
    LOG_I(PHY,"Starting ru_thread %d, is_slave %d, send_dmrs %d\n",ru_id,ru->is_slave,ru->generate_dmrs_sync);
2685 2686

    init_RU_proc(ru);
Raymond Knopp's avatar
Raymond Knopp committed
2687
  } // for ru_id
2688
  
2689
  //  sleep(1);
2690
  LOG_D(HW,"[lte-softmodem.c] RU threads created\n");
Raymond Knopp's avatar
Raymond Knopp committed
2691 2692
}

Wang Tsu-Han's avatar
Wang Tsu-Han committed
2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723
void stop_ru(RU_t *ru) {

#if defined(PRE_SCD_THREAD) || defined(PHY_TX_THREAD)
  int *status;
#endif
  printf("Stopping RU %p processing threads\n",(void*)ru);
#if defined(PRE_SCD_THREAD)
  if(ru){
    ru->proc.instance_pre_scd = 0;
    pthread_cond_signal( &ru->proc.cond_pre_scd );
    pthread_join(ru->proc.pthread_pre_scd, (void**)&status );
    pthread_mutex_destroy(&ru->proc.mutex_pre_scd );
    pthread_cond_destroy(&ru->proc.cond_pre_scd );
  }
#endif
#ifdef PHY_TX_THREAD
  if(ru){
      ru->proc.instance_cnt_phy_tx = 0;
      pthread_cond_signal(&ru->proc.cond_phy_tx);
      pthread_join( ru->proc.pthread_phy_tx, (void**)&status );
      pthread_mutex_destroy( &ru->proc.mutex_phy_tx );
      pthread_cond_destroy( &ru->proc.cond_phy_tx );
      ru->proc.instance_cnt_rf_tx = 0;
      pthread_cond_signal(&ru->proc.cond_rf_tx);
      pthread_join( ru->proc.pthread_rf_tx, (void**)&status );
      pthread_mutex_destroy( &ru->proc.mutex_rf_tx );
      pthread_cond_destroy( &ru->proc.cond_rf_tx );
  }
#endif
}

Robert Schmidt's avatar
Robert Schmidt committed
2724 2725 2726 2727
void stop_RU(int nb_ru)
{
  for (int inst = 0; inst < nb_ru; inst++) {
    LOG_I(PHY, "Stopping RU %d processing threads\n", inst);
Robert Schmidt's avatar
Robert Schmidt committed
2728
    kill_RU_proc(RC.ru[inst]);
Robert Schmidt's avatar
Robert Schmidt committed
2729
  }
Raymond Knopp's avatar
Raymond Knopp committed
2730 2731
}

2732 2733 2734 2735 2736 2737 2738
//Some of the member of ru pointer is used in pre_scd.
//This funtion is for initializing ru pointer for L2 FAPI simulator.
#if defined(PRE_SCD_THREAD)
void init_ru_vnf(void) {
  int ru_id;
  RU_t *ru;
  RU_proc_t *proc;
2739
  //  PHY_VARS_eNB *eNB0= (PHY_VARS_eNB *)NULL;
2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752
  int i;
  int CC_id;
  dlsch_ue_select_tbl_in_use = 1;
  // create status mask
  RC.ru_mask = 0;
  pthread_mutex_init(&RC.ru_mutex,NULL);
  pthread_cond_init(&RC.ru_cond,NULL);
  // read in configuration file)
  printf("configuring RU from file\n");
  RCconfig_RU();
  LOG_I(PHY,"number of L1 instances %d, number of RU %d, number of CPU cores %d\n",RC.nb_L1_inst,RC.nb_RU,get_nprocs());

  if (RC.nb_CC != 0)
2753 2754
    for (i=0; i<RC.nb_L1_inst; i++)
      for (CC_id=0; CC_id<RC.nb_CC[i]; CC_id++) RC.eNB[i][CC_id]->num_RU=0;
2755 2756

  LOG_D(PHY,"Process RUs RC.nb_RU:%d\n",RC.nb_RU);
2757 2758

  for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
2759 2760
    LOG_D(PHY,"Process RC.ru[%d]\n",ru_id);
    ru               = RC.ru[ru_id];
2761 2762
    //    ru->rf_config_file = rf_config_file;
    ru->idx          = ru_id;
2763 2764 2765 2766 2767
    ru->ts_offset    = 0;
    // use eNB_list[0] as a reference for RU frame parameters
    // NOTE: multiple CC_id are not handled here yet!

    if (ru->num_eNB > 0) {
2768 2769
      //      LOG_D(PHY, "%s() RC.ru[%d].num_eNB:%d ru->eNB_list[0]:%p RC.eNB[0][0]:%p rf_config_file:%s\n", __FUNCTION__, ru_id, ru->num_eNB, ru->eNB_list[0], RC.eNB[0][0], ru->rf_config_file);
      if (ru->eNB_list[0] == 0) {
2770 2771 2772
        LOG_E(PHY,"%s() DJP - ru->eNB_list ru->num_eNB are not initialized - so do it manually\n", __FUNCTION__);
        ru->eNB_list[0] = RC.eNB[0][0];
        ru->num_eNB=1;
2773 2774 2775 2776
        //
        // DJP - feptx_prec() / feptx_ofdm() parses the eNB_list (based on num_eNB) and copies the txdata_F to txdata in RU
        //
      } else {
2777 2778 2779 2780
        LOG_E(PHY,"DJP - delete code above this %s:%d\n", __FILE__, __LINE__);
      }
    }

2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801
    // frame_parms is not used in L2 FAPI simulator
    /*
        eNB0             = ru->eNB_list[0];
        LOG_D(PHY, "RU FUnction:%d ru->if_south:%d\n", ru->function, ru->if_south);
        LOG_D(PHY, "eNB0:%p\n", eNB0);
        if (eNB0)
        {
          if ((ru->function != NGFI_RRU_IF5) && (ru->function != NGFI_RRU_IF4p5))
            AssertFatal(eNB0!=NULL,"eNB0 is null!\n");

          if (eNB0) {
            LOG_I(PHY,"Copying frame parms from eNB %d to ru %d\n",eNB0->Mod_id,ru->idx);
            memcpy((void*)&ru->frame_parms,(void*)&eNB0->frame_parms,sizeof(LTE_DL_FRAME_PARMS));

            // attach all RU to all eNBs in its list/
            LOG_D(PHY,"ru->num_eNB:%d eNB0->num_RU:%d\n", ru->num_eNB, eNB0->num_RU);
            for (i=0;i<ru->num_eNB;i++) {
              eNB0 = ru->eNB_list[i];
              eNB0->RU_list[eNB0->num_RU++] = ru;
            }
          }
2802
        }
2803
    */
2804
    LOG_I(PHY,"Initializing RRU descriptor %d : (%s,%s,%d)\n",ru_id,ru_if_types[ru->if_south],eNB_timing[ru->if_timing],ru->function);
2805
    //    set_function_spec_param(ru);
2806
    LOG_I(PHY,"Starting ru_thread %d\n",ru_id);
2807
    //    init_RU_proc(ru);
2808
    proc = &ru->proc;
2809
    memset((void *)proc,0,sizeof(RU_proc_t));
2810 2811 2812
    proc->instance_pre_scd = -1;
    pthread_mutex_init( &proc->mutex_pre_scd, NULL);
    pthread_cond_init( &proc->cond_pre_scd, NULL);
2813
    pthread_create(&proc->pthread_pre_scd, NULL, pre_scd_thread, (void *)ru);
2814 2815 2816 2817 2818 2819 2820 2821
    pthread_setname_np(proc->pthread_pre_scd, "pre_scd_thread");
  } // for ru_id

  //  sleep(1);
  LOG_D(HW,"[lte-softmodem.c] RU threads created\n");
}
#endif

Raymond Knopp's avatar
Raymond Knopp committed
2822

2823 2824 2825 2826 2827 2828 2829
/* --------------------------------------------------------*/
/* from here function to use configuration module          */
void RCconfig_RU(void) {
  int               j                             = 0;
  int               i                             = 0;
  paramdef_t RUParams[] = RUPARAMS_DESC;
  paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0};
2830
  config_getlist( &RUParamList,RUParams,sizeof(RUParams)/sizeof(paramdef_t), NULL);
Raymond Knopp's avatar
Raymond Knopp committed
2831

2832
  if ( RUParamList.numelt > 0) {
2833
    RC.ru = (RU_t **)malloc(RC.nb_RU*sizeof(RU_t *));
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2834
    RC.ru_mask=(1<<RC.nb_RU) - 1;
2835 2836 2837
    printf("Set RU mask to %lx\n",RC.ru_mask);

    for (j = 0; j < RC.nb_RU; j++) {
2838 2839
      RC.ru[j]                                    = (RU_t *)malloc(sizeof(RU_t));
      memset((void *)RC.ru[j],0,sizeof(RU_t));
2840 2841 2842
      RC.ru[j]->idx                                 = j;
      printf("Creating RC.ru[%d]:%p\n", j, RC.ru[j]);
      RC.ru[j]->if_timing                           = synch_to_ext_device;
2843

2844 2845 2846
      if (RC.nb_L1_inst >0)
        RC.ru[j]->num_eNB                           = RUParamList.paramarray[j][RU_ENB_LIST_IDX].numelt;
      else
Raymond Knopp's avatar
Raymond Knopp committed
2847
	RC.ru[j]->num_eNB                           = 0;
2848
      for (i=0;i<RC.ru[j]->num_eNB;i++) RC.ru[j]->eNB_list[i] = RC.eNB[RUParamList.paramarray[j][RU_ENB_LIST_IDX].iptr[i]][0];     
2849

2850
      RC.ru[j]->has_ctrl_prt                        = 1;
2851

2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869
      if (config_isparamset(RUParamList.paramarray[j], RU_SDR_ADDRS)) {
        RC.ru[j]->openair0_cfg.sdr_addrs = strdup(*(RUParamList.paramarray[j][RU_SDR_ADDRS].strptr));
      }

      if (config_isparamset(RUParamList.paramarray[j], RU_SDR_CLK_SRC)) {
        if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "internal") == 0) {
          RC.ru[j]->openair0_cfg.clock_source = internal;
          LOG_D(PHY, "RU clock source set as internal\n");
        } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "external") == 0) {
          RC.ru[j]->openair0_cfg.clock_source = external;
          LOG_D(PHY, "RU clock source set as external\n");
        } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "gpsdo") == 0) {
          RC.ru[j]->openair0_cfg.clock_source = gpsdo;
          LOG_D(PHY, "RU clock source set as gpsdo\n");
        } else {
          LOG_E(PHY, "Erroneous RU clock source in the provided configuration file: '%s'\n", *(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr));
        }
      }
2870 2871 2872 2873 2874

      if (strcmp(*(RUParamList.paramarray[j][RU_LOCAL_RF_IDX].strptr), "yes") == 0) {
	if ( !(config_isparamset(RUParamList.paramarray[j],RU_LOCAL_IF_NAME_IDX)) ) {
	  RC.ru[j]->if_south                        = LOCAL_RF;
	  RC.ru[j]->function                        = eNodeB_3GPP;
2875
          RC.ru[j]->state                           = RU_RUN;
2876 2877 2878 2879 2880 2881 2882 2883 2884
	  printf("Setting function for RU %d to eNodeB_3GPP\n",j);
        }
        else { 
          RC.ru[j]->eth_params.local_if_name            = strdup(*(RUParamList.paramarray[j][RU_LOCAL_IF_NAME_IDX].strptr));    
          RC.ru[j]->eth_params.my_addr                  = strdup(*(RUParamList.paramarray[j][RU_LOCAL_ADDRESS_IDX].strptr)); 
          RC.ru[j]->eth_params.remote_addr              = strdup(*(RUParamList.paramarray[j][RU_REMOTE_ADDRESS_IDX].strptr));
          RC.ru[j]->eth_params.my_portd                 = *(RUParamList.paramarray[j][RU_LOCAL_PORTD_IDX].uptr);
          RC.ru[j]->eth_params.remote_portd             = *(RUParamList.paramarray[j][RU_REMOTE_PORTD_IDX].uptr);

2885 2886
	  // Check if control port set
	  if  (!(config_isparamset(RUParamList.paramarray[j],RU_REMOTE_PORTC_IDX)) ){
2887
	        printf("Removing control port for RU %d\n",j);
2888

2889 2890
		RC.ru[j]->has_ctrl_prt			      = 0;
          }
2891 2892 2893 2894 2895 2896
	  else {
	    RC.ru[j]->eth_params.my_portc                 = *(RUParamList.paramarray[j][RU_LOCAL_PORTC_IDX].uptr);
	    RC.ru[j]->eth_params.remote_portc             = *(RUParamList.paramarray[j][RU_REMOTE_PORTC_IDX].uptr);
	    printf(" Control port %u \n",RC.ru[j]->eth_params.my_portc);
	  
	  }
2897

2898 2899 2900 2901
	  if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp") == 0) {
	    RC.ru[j]->if_south                        = LOCAL_RF;
	    RC.ru[j]->function                        = NGFI_RRU_IF5;
	    RC.ru[j]->eth_params.transp_preference    = ETH_UDP_MODE;
2902
           
2903 2904 2905 2906 2907
	    printf("Setting function for RU %d to NGFI_RRU_IF5 (udp)\n",j);
	  } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw") == 0) {
	    RC.ru[j]->if_south                        = LOCAL_RF;
	    RC.ru[j]->function                        = NGFI_RRU_IF5;
	    RC.ru[j]->eth_params.transp_preference    = ETH_RAW_MODE;
2908
	  
2909 2910 2911 2912 2913
	    printf("Setting function for RU %d to NGFI_RRU_IF5 (raw)\n",j);
	  } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp_if4p5") == 0) {
	    RC.ru[j]->if_south                        = LOCAL_RF;
	    RC.ru[j]->function                        = NGFI_RRU_IF4p5;
	    RC.ru[j]->eth_params.transp_preference    = ETH_UDP_IF4p5_MODE;
2914
	 
2915 2916 2917 2918 2919
	    printf("Setting function for RU %d to NGFI_RRU_IF4p5 (udp)\n",j);
	  } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw_if4p5") == 0) {
	    RC.ru[j]->if_south                        = LOCAL_RF;
	    RC.ru[j]->function                        = NGFI_RRU_IF4p5;
	    RC.ru[j]->eth_params.transp_preference    = ETH_RAW_IF4p5_MODE;
2920
	
2921 2922
	    printf("Setting function for RU %d to NGFI_RRU_IF4p5 (raw)\n",j);
	  }
2923
          printf("RU %d is_slave=%s\n",j,*(RUParamList.paramarray[j][RU_IS_SLAVE_IDX].strptr));
2924 2925
          if (strcmp(*(RUParamList.paramarray[j][RU_IS_SLAVE_IDX].strptr), "yes") == 0) RC.ru[j]->is_slave=1;
          else RC.ru[j]->is_slave=0;
2926 2927 2928
          printf("RU %d ota_sync_enabled=%s\n",j,*(RUParamList.paramarray[j][RU_OTA_SYNC_ENABLE_IDX].strptr));
          if (strcmp(*(RUParamList.paramarray[j][RU_OTA_SYNC_ENABLE_IDX].strptr), "yes") == 0) RC.ru[j]->ota_sync_enable=1;
          else RC.ru[j]->ota_sync_enable=0;
2929 2930 2931 2932
	}
	RC.ru[j]->max_pdschReferenceSignalPower     = *(RUParamList.paramarray[j][RU_MAX_RS_EPRE_IDX].uptr);;
	RC.ru[j]->max_rxgain                        = *(RUParamList.paramarray[j][RU_MAX_RXGAIN_IDX].uptr);
	RC.ru[j]->num_bands                         = RUParamList.paramarray[j][RU_BAND_LIST_IDX].numelt;
2933 2934
	/* sf_extension is in unit of samples for 30.72MHz here, has to be scaled later */
        RC.ru[j]->sf_extension                      = *(RUParamList.paramarray[j][RU_SF_EXTENSION_IDX].uptr);
2935 2936 2937 2938
	for (i=0;i<RC.ru[j]->num_bands;i++) RC.ru[j]->band[i] = RUParamList.paramarray[j][RU_BAND_LIST_IDX].iptr[i]; 
      } //strcmp(local_rf, "yes") == 0
      else {
	printf("RU %d: Transport %s\n",j,*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr));
2939
	
2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963
        RC.ru[j]->eth_params.local_if_name	      = strdup(*(RUParamList.paramarray[j][RU_LOCAL_IF_NAME_IDX].strptr));    
        RC.ru[j]->eth_params.my_addr		      = strdup(*(RUParamList.paramarray[j][RU_LOCAL_ADDRESS_IDX].strptr)); 
        RC.ru[j]->eth_params.remote_addr	      = strdup(*(RUParamList.paramarray[j][RU_REMOTE_ADDRESS_IDX].strptr));
        RC.ru[j]->eth_params.my_portc		      = *(RUParamList.paramarray[j][RU_LOCAL_PORTC_IDX].uptr);
        RC.ru[j]->eth_params.remote_portc	      = *(RUParamList.paramarray[j][RU_REMOTE_PORTC_IDX].uptr);
        RC.ru[j]->eth_params.my_portd		      = *(RUParamList.paramarray[j][RU_LOCAL_PORTD_IDX].uptr);
        RC.ru[j]->eth_params.remote_portd	      = *(RUParamList.paramarray[j][RU_REMOTE_PORTD_IDX].uptr);
	if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp") == 0) {
	  RC.ru[j]->if_south                     = REMOTE_IF5;
	  RC.ru[j]->function                     = NGFI_RAU_IF5;
	  RC.ru[j]->eth_params.transp_preference = ETH_UDP_MODE;
	} else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw") == 0) {
	  RC.ru[j]->if_south                     = REMOTE_IF5;
	  RC.ru[j]->function                     = NGFI_RAU_IF5;
	  RC.ru[j]->eth_params.transp_preference = ETH_RAW_MODE;
	} else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp_if4p5") == 0) {
	  RC.ru[j]->if_south                     = REMOTE_IF4p5;
	  RC.ru[j]->function                     = NGFI_RAU_IF4p5;
	  RC.ru[j]->eth_params.transp_preference = ETH_UDP_IF4p5_MODE;
	} else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw_if4p5") == 0) {
	  RC.ru[j]->if_south                     = REMOTE_IF4p5;
	  RC.ru[j]->function                     = NGFI_RAU_IF4p5;
	  RC.ru[j]->eth_params.transp_preference = ETH_RAW_IF4p5_MODE;
	}
2964 2965
        if (strcmp(*(RUParamList.paramarray[j][RU_IS_SLAVE_IDX].strptr), "yes") == 0) RC.ru[j]->is_slave=1;
        else RC.ru[j]->is_slave=0;
2966 2967 2968 2969
      }  /* strcmp(local_rf, "yes") != 0 */

      RC.ru[j]->nb_tx                             = *(RUParamList.paramarray[j][RU_NB_TX_IDX].uptr);
      RC.ru[j]->nb_rx                             = *(RUParamList.paramarray[j][RU_NB_RX_IDX].uptr);
2970 2971
      RC.ru[j]->att_tx                            = *(RUParamList.paramarray[j][RU_ATT_TX_IDX].uptr);
      RC.ru[j]->att_rx                            = *(RUParamList.paramarray[j][RU_ATT_RX_IDX].uptr);
2972 2973
    }// j=0..num_rus
  } else {
2974
    RC.nb_RU = 0;
2975 2976 2977 2978
  } // setting != NULL

  return;
}
Raymond Knopp's avatar
Raymond Knopp committed
2979 2980