lte-ru.c 123 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
 */
yilmazt's avatar
yilmazt committed
21

Raymond Knopp's avatar
Raymond Knopp committed
22 23
/*! \file lte-ru.c
 * \brief Top-level threads for RU entity
Raymond Knopp's avatar
Raymond Knopp committed
24
 * \author R. Knopp, F. Kaltenberger, Navid Nikaein
Raymond Knopp's avatar
Raymond Knopp committed
25
 * \date 2019
Raymond Knopp's avatar
Raymond Knopp committed
26 27 28 29 30 31
 * \version 0.1
 * \company Eurecom
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr
 * \note
 * \warning
 */
yilmazt's avatar
yilmazt committed
32

Raymond Knopp's avatar
Raymond Knopp committed
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
#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 "../../ARCH/COMMON/common_lib.h"
55
#include "../../ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h"
Raymond Knopp's avatar
Raymond Knopp committed
56

yilmazt's avatar
yilmazt committed
57
#include "PHY/defs_common.h"
58
#include "PHY/phy_extern.h"
yilmazt's avatar
yilmazt committed
59 60
#include "PHY/types.h"
#include "PHY/INIT/phy_init.h"
61
#include "PHY/LTE_ESTIMATION/lte_estimation.h"
Raymond Knopp's avatar
Raymond Knopp committed
62
#include "PHY/LTE_REFSIG/lte_refsig.h"
Raymond Knopp's avatar
Raymond Knopp committed
63 64
#include "PHY/LTE_TRANSPORT/if4_tools.h"
#include "PHY/LTE_TRANSPORT/if5_tools.h"
65
#include "PHY/LTE_TRANSPORT/transport_proto.h"
yilmazt's avatar
yilmazt committed
66 67
#include "PHY_INTERFACE/phy_interface.h"
#include "LAYER2/MAC/mac_extern.h"
68 69 70 71
#include "LAYER2/MAC/mac.h"
#include "LAYER2/MAC/mac_extern.h"
#include "LAYER2/MAC/mac_proto.h"
#include "RRC/LTE/rrc_extern.h"
yilmazt's avatar
yilmazt committed
72 73
#include "SCHED/sched_eNB.h"
#include "UTIL/OPT/opt.h"
Raymond Knopp's avatar
Raymond Knopp committed
74 75 76
#include "UTIL/OTG/otg_tx.h"
#include "UTIL/OTG/otg_externs.h"
#include "UTIL/MATH/oml.h"
yilmazt's avatar
yilmazt committed
77
#include "common/utils/LOG/log.h"
78
#include "common/utils/LOG/vcd_signal_dumper.h"
yilmazt's avatar
yilmazt committed
79
#include "nfapi/oai_integration/vendor_ext.h"
Raymond Knopp's avatar
Raymond Knopp committed
80
#include "enb_config.h"
81
#include "targets/RT/USER/lte-softmodem.h"
Raymond Knopp's avatar
Raymond Knopp committed
82 83
//#include "PHY/TOOLS/time_meas.h"

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

88 89 90
#include "ENB_APP/enb_paramdef.h"
#include "common/config/config_userapi.h"

Raymond Knopp's avatar
Raymond Knopp committed
91
#ifndef OPENAIR2
92
  #include "UTIL/OTG/otg_extern.h"
Raymond Knopp's avatar
Raymond Knopp committed
93 94
#endif

95 96 97 98
#include "s1ap_eNB.h"
#include "SIMULATION/ETH_TRANSPORT/proto.h"


Raymond Knopp's avatar
Raymond Knopp committed
99 100
#include "T.h"

Wang Tsu-Han's avatar
Wang Tsu-Han committed
101
#include "pdcp.h"
Wang Tsu-Han's avatar
Wang Tsu-Han committed
102

103
extern volatile int oai_exit;
104
extern int emulate_rf;
105
extern int numerology;
106
extern clock_source_t clock_source;
Raymond Knopp's avatar
Raymond Knopp committed
107

108 109
extern PARALLEL_CONF_t get_thread_parallel_conf(void);
extern WORKER_CONF_t   get_thread_worker_conf(void);
110
extern void phy_init_RU(RU_t *);
111

Robert Schmidt's avatar
Robert Schmidt committed
112
void stop_RU(int nb_ru);
113
void do_ru_synch(RU_t *ru);
Raymond Knopp's avatar
Raymond Knopp committed
114

115
void configure_ru(int idx,
116
                  void *arg);
117 118

void configure_rru(int idx,
119
                   void *arg);
120

121
void reset_proc(RU_t *ru);
122
int connect_rau(RU_t *ru);
Raymond Knopp's avatar
Raymond Knopp committed
123

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

126
extern uint16_t sf_ahead;
127

128
#if defined(PRE_SCD_THREAD)
129
  extern uint8_t dlsch_ue_select_tbl_in_use;
130
  void init_ru_vnf(void);
131 132 133
#endif


134 135 136
/*************************************************************/
/* Functions to attach and configure RRU                     */

137

Raymond Knopp's avatar
Raymond Knopp committed
138 139 140 141
/*************************************************************/
/* Southbound Fronthaul functions, RCC/RAU                   */

// southbound IF5 fronthaul for 16-bit OAI format
142
static inline void fh_if5_south_out(RU_t *ru,int frame, int subframe, uint64_t timestamp) {
143
  if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );
144
  send_IF5(ru, timestamp, subframe, &ru->seqno, IF5_RRH_GW_DL);
Raymond Knopp's avatar
Raymond Knopp committed
145 146
}

147

Raymond Knopp's avatar
Raymond Knopp committed
148
// southbound IF5 fronthaul for Mobipass packet format
149
static inline void fh_if5_mobipass_south_out(RU_t *ru,int frame, int subframe, uint64_t timestamp) {
150
  if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );
151
  send_IF5(ru, timestamp, subframe, &ru->seqno, IF5_MOBIPASS); 
Raymond Knopp's avatar
Raymond Knopp committed
152 153
}

yilmazt's avatar
yilmazt committed
154

Raymond Knopp's avatar
Raymond Knopp committed
155
// southbound IF4p5 fronthaul
yilmazt's avatar
yilmazt committed
156 157 158 159 160
static inline void fh_if4p5_south_out(RU_t *ru,
                                      int frame,
                                      int subframe,
                                      uint64_t timestamp)
{
161
  if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );
yilmazt's avatar
yilmazt committed
162 163
  LOG_D(PHY,"ENTERED fh_if4p5_south_out   Sending IF4p5 for frame %d subframe %d ru %d\n",ru->proc.frame_tx,ru->proc.tti_tx,ru->idx);
  if (subframe_select(ru->frame_parms,subframe)!=SF_UL) {
164
    send_IF4p5(ru,frame, subframe, IF4p5_PDLFFT);
165
    ru->south_out_cnt++;
Raymond Knopp's avatar
Raymond Knopp committed
166
    LOG_D(PHY,"south_out_cnt %d\n",ru->south_out_cnt);
167
  }
magounak's avatar
magounak committed
168 169 170 171
/*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 );
  }*/
yilmazt's avatar
yilmazt committed
172 173
  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.tti_tx);
Raymond Knopp's avatar
Raymond Knopp committed
174 175
}

yilmazt's avatar
yilmazt committed
176

Raymond Knopp's avatar
Raymond Knopp committed
177 178 179
/*************************************************************/
/* Input Fronthaul from south RCC/RAU                        */

180
// Synchronous if5 from south
181 182 183 184
void fh_if5_south_in(RU_t *ru,
		             int *frame,
					 int *subframe)
{
Guy De Souza's avatar
Guy De Souza committed
185
  LTE_DL_FRAME_PARMS *fp = ru->frame_parms;
186
  RU_proc_t *proc = &ru->proc;
187
  recv_IF5(ru, &proc->timestamp_rx, *subframe, IF5_RRH_GW_UL);
Raymond Knopp's avatar
Raymond Knopp committed
188
  proc->frame_rx    = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023;
189
  proc->tti_rx = (proc->timestamp_rx / fp->samples_per_tti)%10;
Raymond Knopp's avatar
Raymond Knopp committed
190 191
  
  if (proc->first_rx == 0) {
192 193
    if (proc->tti_rx != *subframe){
      LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->tti_rx %d, subframe %d)\n",proc->tti_rx,*subframe);
Raymond Knopp's avatar
Raymond Knopp committed
194 195
      exit_fun("Exiting");
    }
196

Raymond Knopp's avatar
Raymond Knopp committed
197
    if (proc->frame_rx != *frame) {
198
      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
199 200 201 202 203
      exit_fun("Exiting");
    }
  } else {
    proc->first_rx = 0;
    *frame = proc->frame_rx;
204
    *subframe = proc->tti_rx;        
Raymond Knopp's avatar
Raymond Knopp committed
205 206 207 208 209
  }      
  
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
}

yilmazt's avatar
yilmazt committed
210

211
// Synchronous if4p5 from south
212 213 214 215
void fh_if4p5_south_in(RU_t *ru,
		               int *frame,
					   int *subframe)
{
Guy De Souza's avatar
Guy De Souza committed
216
  LTE_DL_FRAME_PARMS *fp = ru->frame_parms;
217 218
  RU_proc_t *proc = &ru->proc;
  int f,sf;
Raymond Knopp's avatar
Raymond Knopp committed
219 220
  uint16_t packet_type;
  uint32_t symbol_number=0;
221
  uint32_t symbol_mask_full;
222
  int pultick_received=0;
223 224 225 226 227

  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; 
228 229 230 231 232
  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);
233
	 LOG_D(PHY,"fh_if4p5_south_in: RU %d, frame %d, subframe %d, f %d, sf %d\n",ru->idx,*frame,*subframe,f,sf);
234 235 236 237 238
       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++;
239
/*
240 241
         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);       
242 243
         else break; */
         if (f==*frame || sf==*subframe) break;
244
       } else if (packet_type == IF4p5_PRACH) {
245
      // nothing in RU for RAU
246
       }
247 248
       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);    
249 250 251 252 253
  }
  else {
   f = *frame;
   sf = *subframe;
  }
Raymond Knopp's avatar
Raymond Knopp committed
254

magounak's avatar
magounak committed
255
  //calculate timestamp_rx, timestamp_tx based on frame and subframe
256
  proc->tti_rx  = sf;
yilmazt's avatar
yilmazt committed
257
  proc->frame_rx= f;
258
  proc->timestamp_rx = ((proc->frame_rx * 10)  + proc->tti_rx ) * fp->samples_per_tti ;
259
  //  proc->timestamp_tx = proc->timestamp_rx +  (4*fp->samples_per_tti);
cdxu0312's avatar
cdxu0312 committed
260
  if (get_nprocs()<=4) {
yilmazt's avatar
yilmazt committed
261 262
     proc->tti_tx  = (sf+sf_ahead)%10;
     proc->frame_tx= (sf>(9-sf_ahead)) ? (f+1)&1023 : f;
cdxu0312's avatar
cdxu0312 committed
263 264
  }

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

Raymond Knopp's avatar
Raymond Knopp committed
267
  if (proc->first_rx == 0) {
yilmazt's avatar
yilmazt committed
268 269 270
    if (proc->tti_rx != *subframe) {
      LOG_E(PHY,"Received Timestamp (IF4p5) doesn't correspond to the time we think it is (proc->tti_rx %d, subframe %d, symbol_mask %x)\n",
    		  proc->tti_rx,*subframe,proc->symbol_mask[*subframe]);
271 272
      *subframe=sf; 
      //exit_fun("Exiting");
Raymond Knopp's avatar
Raymond Knopp committed
273
    }
274
    if (ru->cmd != WAIT_RESYNCH && proc->frame_rx != *frame) {
yilmazt's avatar
yilmazt committed
275 276
      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]);
277
      //exit_fun("Exiting");
Raymond Knopp's avatar
Raymond Knopp committed
278
    }
279 280 281
    else if (ru->cmd == WAIT_RESYNCH && proc->frame_rx != *frame){
       ru->cmd=EMPTY;
       *frame=proc->frame_rx; 
Raymond Knopp's avatar
Raymond Knopp committed
282 283 284 285
    }
  } else {
    proc->first_rx = 0;
    *frame = proc->frame_rx;
286
    *subframe = proc->tti_rx;        
Raymond Knopp's avatar
Raymond Knopp committed
287
  }
288

magounak's avatar
magounak committed
289
  /*if (ru == RC.ru[0] || ru == RC.ru[1]) {
290 291
    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 );
292
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_RU, f );
293
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_RX0_RU, sf );
294
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, proc->frame_tx );
295
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, proc->tti_tx );
magounak's avatar
magounak committed
296 297
  }*/

yilmazt's avatar
yilmazt committed
298
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_IF4P5_SOUTH_IN_RU   +ru->idx,f );
magounak's avatar
magounak committed
299
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_IF4P5_SOUTH_IN_RU+ru->idx,sf);
300

301
  proc->symbol_mask[sf] = 0;
yilmazt's avatar
yilmazt committed
302
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff);
303 304
  LOG_D(PHY,"RU %d: fh_if4p5_south_in returning ...\n",ru->idx);
  //  usleep(100);
Raymond Knopp's avatar
Raymond Knopp committed
305 306
}

yilmazt's avatar
yilmazt committed
307

Raymond Knopp's avatar
Raymond Knopp committed
308
// Dummy FH from south for getting synchronization from master RU
309 310 311 312
void fh_slave_south_in(RU_t *ru,
		               int *frame,
					   int *subframe)
{
Raymond Knopp's avatar
Raymond Knopp committed
313 314
  // 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
315
  RU_proc_t *proc=&ru->proc;
Raymond Knopp's avatar
Raymond Knopp committed
316 317 318 319 320 321 322

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

yilmazt's avatar
yilmazt committed
323

324
// asynchronous inbound if5 fronthaul from south (Mobipass)
325 326 327 328
void fh_if5_south_asynch_in_mobipass(RU_t *ru,
		                             int *frame,
									 int *subframe)
{
yilmazt's avatar
yilmazt committed
329
  RU_proc_t *proc        = &ru->proc;
Guy De Souza's avatar
Guy De Souza committed
330
  LTE_DL_FRAME_PARMS *fp = ru->frame_parms;
331
  recv_IF5(ru, &proc->timestamp_rx, *subframe, IF5_MOBIPASS);
332 333 334
  pthread_mutex_lock(&proc->mutex_asynch_rxtx);
  int offset_mobipass = 40120;
  pthread_mutex_lock(&proc->mutex_asynch_rxtx);
335
  proc->tti_rx = ((proc->timestamp_rx-offset_mobipass)/fp->samples_per_tti)%10;
336
  proc->frame_rx    = ((proc->timestamp_rx-offset_mobipass)/(fp->samples_per_tti*10))&1023;
Raymond Knopp's avatar
Raymond Knopp committed
337

338
  proc->tti_rx = (proc->timestamp_rx/fp->samples_per_tti)%10;
339
  proc->frame_rx    = (proc->timestamp_rx/(10*fp->samples_per_tti))&1023;
Raymond Knopp's avatar
Raymond Knopp committed
340

341 342
  if (proc->first_rx == 1) {
    proc->first_rx =2;
343
    *subframe = proc->tti_rx;
Raymond Knopp's avatar
Raymond Knopp committed
344
    *frame    = proc->frame_rx; 
345
    LOG_E(PHY,"[Mobipass]timestamp_rx:%llu, frame_rx %d, subframe: %d\n",(unsigned long long int)proc->timestamp_rx,proc->frame_rx,proc->tti_rx);
346
  } else {
347
    if (proc->tti_rx != *subframe) {
348
        proc->first_rx++;
349
        LOG_E(PHY,"[Mobipass]timestamp:%llu, tti_rx %d is not what we expect %d, first_rx:%d\n",(unsigned long long int)proc->timestamp_rx, proc->tti_rx,*subframe, proc->first_rx);
350
      //exit_fun("Exiting");
Raymond Knopp's avatar
Raymond Knopp committed
351
    }
352

Raymond Knopp's avatar
Raymond Knopp committed
353
    if (proc->frame_rx != *frame) {
354 355 356
      proc->first_rx++;
      LOG_E(PHY,"[Mobipass]timestamp:%llu, frame_rx %d is not what we expect %d, first_rx:%d\n",(unsigned long long int)proc->timestamp_rx,proc->frame_rx,*frame, proc->first_rx);
      // exit_fun("Exiting");
Raymond Knopp's avatar
Raymond Knopp committed
357
    }
358

359
    // temporary solution
360
      *subframe = proc->tti_rx;
361
      *frame    = proc->frame_rx;
Raymond Knopp's avatar
Raymond Knopp committed
362
  }
363 364

  pthread_mutex_unlock(&proc->mutex_asynch_rxtx);
365
} // eNodeB_3GPP_BBU
Raymond Knopp's avatar
Raymond Knopp committed
366

yilmazt's avatar
yilmazt committed
367

Raymond Knopp's avatar
Raymond Knopp committed
368
// asynchronous inbound if4p5 fronthaul from south
369 370 371 372
void fh_if4p5_south_asynch_in(RU_t *ru,
		                      int *frame,
							  int *subframe)
{
Guy De Souza's avatar
Guy De Souza committed
373
  LTE_DL_FRAME_PARMS *fp = ru->frame_parms;
yilmazt's avatar
yilmazt committed
374
  RU_proc_t *proc        = &ru->proc;
Raymond Knopp's avatar
Raymond Knopp committed
375
  uint16_t packet_type;
Raymond Knopp's avatar
Raymond Knopp committed
376
  uint32_t symbol_number,symbol_mask,prach_rx;
377
  uint32_t got_prach_info=0;
Raymond Knopp's avatar
Raymond Knopp committed
378
  symbol_number = 0;
379 380
  symbol_mask   = (1<<fp->symbols_per_tti)-1;
  prach_rx      = 0;
Raymond Knopp's avatar
Raymond Knopp committed
381 382

  do {   // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!!
yilmazt's avatar
yilmazt committed
383
	recv_IF4p5(ru, &proc->frame_rx, &proc->tti_rx, &packet_type, &symbol_number);
384

385
    if (ru->cmd == STOP_RU) break;
386 387
    // grab first prach information for this new subframe
    if (got_prach_info==0) {
388
      prach_rx       = is_prach_subframe(fp, proc->frame_rx, proc->tti_rx);
389 390
      got_prach_info = 1;
    }
391

Raymond Knopp's avatar
Raymond Knopp committed
392 393
    if (proc->first_rx != 0) {
      *frame = proc->frame_rx;
394
      *subframe = proc->tti_rx;
Raymond Knopp's avatar
Raymond Knopp committed
395
      proc->first_rx = 0;
396
    } else {
Raymond Knopp's avatar
Raymond Knopp committed
397
      if (proc->frame_rx != *frame) {
398 399
        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
400
      }
401

402 403
      if (proc->tti_rx != *subframe) {
	LOG_E(PHY,"tti_rx %d is not what we expect %d\n",proc->tti_rx,*subframe);
Raymond Knopp's avatar
Raymond Knopp committed
404 405 406
	exit_fun("Exiting");
      }
    }
407

408 409
    if      (packet_type == IF4p5_PULFFT)       symbol_mask &= (~(1<<symbol_number));
    else if (packet_type == IF4p5_PRACH)        prach_rx    &= (~0x1);
410

411
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
412 413 414 415
    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);
Raymond Knopp's avatar
Raymond Knopp committed
416

417
#endif
418 419
  } while( (symbol_mask > 0) || (prach_rx >0));   // haven't received all PUSCH symbols and PRACH information
}
Raymond Knopp's avatar
Raymond Knopp committed
420 421 422 423 424 425



/*************************************************************/
/* Input Fronthaul from North RRU                            */

426
// 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
427
// receives one subframe's worth of IF4p5 OFDM symbols and OFDM modulates
428 429 430 431
void fh_if4p5_north_in(RU_t *ru,
		               int *frame,
					   int *subframe)
{
Raymond Knopp's avatar
Raymond Knopp committed
432 433 434
  uint32_t symbol_number=0;
  uint32_t symbol_mask, symbol_mask_full;
  uint16_t packet_type;
435
  /// **** incoming IF4p5 from remote RCC/RAU **** ///
Raymond Knopp's avatar
Raymond Knopp committed
436 437
  symbol_number = 0;
  symbol_mask = 0;
438
  symbol_mask_full = (1<<ru->frame_parms->symbols_per_tti)-1;
magounak's avatar
magounak committed
439
  LOG_D(PHY,"fh_if4p5_north_in: frame %d, subframe %d\n",*frame,*subframe);
440

Raymond Knopp's avatar
Raymond Knopp committed
441
  do { 
442
    recv_IF4p5(ru, frame, subframe, &packet_type, &symbol_number);
Raymond Knopp's avatar
Raymond Knopp committed
443 444
    symbol_mask = symbol_mask | (1<<symbol_number);
  } while (symbol_mask != symbol_mask_full); 
magounak's avatar
magounak committed
445
  
446
  ru->north_in_cnt++;
447 448
  // dump VCD output for first RU in list
  if (ru == RC.ru[0]) {
449
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, *frame );
450
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, *subframe );
Raymond Knopp's avatar
Raymond Knopp committed
451 452 453
  }
}

454 455 456 457
void fh_if5_north_asynch_in(RU_t *ru,
		                    int *frame,
							int *subframe)
{
Guy De Souza's avatar
Guy De Souza committed
458
  LTE_DL_FRAME_PARMS *fp = ru->frame_parms;
459
  RU_proc_t *proc        = &ru->proc;
460
  int tti_tx,frame_tx;
Raymond Knopp's avatar
Raymond Knopp committed
461 462 463
  openair0_timestamp timestamp_tx;

  recv_IF5(ru, &timestamp_tx, *subframe, IF5_RRH_GW_DL); 
464
      //      printf("Received subframe %d (TS %llu) from RCC\n",tti_tx,timestamp_tx);
Raymond Knopp's avatar
Raymond Knopp committed
465

466
  tti_tx = (timestamp_tx/fp->samples_per_tti)%10;
Raymond Knopp's avatar
Raymond Knopp committed
467 468
  frame_tx    = (timestamp_tx/(fp->samples_per_tti*10))&1023;

Raymond Knopp's avatar
Raymond Knopp committed
469
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, proc->frame_tx );
470
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, proc->tti_tx );
Raymond Knopp's avatar
Raymond Knopp committed
471
  
Raymond Knopp's avatar
Raymond Knopp committed
472
  if (proc->first_tx != 0) {
473
    *subframe = tti_tx;
Raymond Knopp's avatar
Raymond Knopp committed
474 475
    *frame    = frame_tx;
    proc->first_tx = 0;
476
  } else {
yilmazt's avatar
yilmazt committed
477 478
    AssertFatal(tti_tx == *subframe, "tti_tx %d is not what we expect %d\n",tti_tx,*subframe);
    AssertFatal(frame_tx == *frame, "frame_tx %d is not what we expect %d\n",frame_tx,*frame);
Raymond Knopp's avatar
Raymond Knopp committed
479
  }
480
  ru->north_in_cnt++;
Raymond Knopp's avatar
Raymond Knopp committed
481 482
}

yilmazt's avatar
yilmazt committed
483

484 485 486 487
void fh_if4p5_north_asynch_in(RU_t *ru,
		                      int *frame,
							  int *subframe)
{
Guy De Souza's avatar
Guy De Souza committed
488
  LTE_DL_FRAME_PARMS *fp = ru->frame_parms;
489
  RU_proc_t *proc        = &ru->proc;
Raymond Knopp's avatar
Raymond Knopp committed
490 491
  uint16_t packet_type;
  uint32_t symbol_number,symbol_mask,symbol_mask_full;
yilmazt's avatar
yilmazt committed
492
  int tti_tx,frame_tx, ret;
Raymond Knopp's avatar
Raymond Knopp committed
493

Cedric Roux's avatar
Cedric Roux committed
494
  LOG_D(PHY, "%s(ru:%p frame, subframe)\n", __FUNCTION__, ru);
Raymond Knopp's avatar
Raymond Knopp committed
495 496
  symbol_number = 0;
  symbol_mask = 0;
497
  symbol_mask_full = ((subframe_select(fp,*subframe) == SF_S) ? (1<<fp->dl_symbols_in_S_subframe) : (1<<fp->symbols_per_tti))-1;
yilmazt's avatar
yilmazt committed
498 499 500
  LOG_D(PHY,"fh_if4p5_north_asynch_in: RU %d, frame %d, subframe %d\n", ru->idx, *frame, *subframe);

  do {
501
    recv_IF4p5(ru, &frame_tx, &tti_tx, &packet_type, &symbol_number);
yilmazt's avatar
yilmazt committed
502 503 504
    LOG_D(PHY,"income frame.subframe %d.%d, our frame.subframe.symbol_number %d.%d.%d (symbol mask %x)\n",frame_tx,tti_tx,*frame,*subframe,symbol_number,symbol_mask);
    if (ru->cmd == STOP_RU)
    {
Raymond Knopp's avatar
Raymond Knopp committed
505
      LOG_E(PHY,"Got STOP_RU\n");
Wang Tsu-Han's avatar
Wang Tsu-Han committed
506
      AssertFatal((ret=pthread_mutex_lock(&proc->mutex_ru))==0,"mutex_lock returns %d\n",ret);
Raymond Knopp's avatar
Raymond Knopp committed
507
      proc->instance_cnt_ru = -1;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
508
      AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_ru))==0,"mutex_unlock returns %d\n",ret);
509
      ru->cmd=STOP_RU;
Raymond Knopp's avatar
Raymond Knopp committed
510
      return;
511
    } 
512
    if ((subframe_select(fp,tti_tx) == SF_DL) && (symbol_number == 0)) start_meas(&ru->rx_fhaul);
yilmazt's avatar
yilmazt committed
513
    LOG_D(PHY,"subframe %d (%d): frame %d, subframe %d, symbol %d\n", *subframe,subframe_select(fp,*subframe),frame_tx,tti_tx,symbol_number);
514

yilmazt's avatar
yilmazt committed
515 516
    if (proc->first_tx != 0)
    {
Raymond Knopp's avatar
Raymond Knopp committed
517
      *frame    = frame_tx;
518
      *subframe = tti_tx;
Raymond Knopp's avatar
Raymond Knopp committed
519
      proc->first_tx = 0;
520
      symbol_mask_full = ((subframe_select(fp,*subframe) == SF_S) ? (1<<fp->dl_symbols_in_S_subframe) : (1<<fp->symbols_per_tti))-1;
521
    } else {
yilmazt's avatar
yilmazt committed
522 523
     /* AssertFatal(frame_tx == *frame, "frame_tx %d is not what we expect %d\n",frame_tx,*frame);
      AssertFatal(subframe_tx == *subframe, "In frame_tx %d : subframe_tx %d is not what we expect %d\n",frame_tx,subframe_tx,*subframe);
524 525
     */
      *frame    = frame_tx;
yilmazt's avatar
yilmazt committed
526
      *subframe = tti_tx;
Raymond Knopp's avatar
Raymond Knopp committed
527
    }
528

Raymond Knopp's avatar
Raymond Knopp committed
529 530 531
    if (packet_type == IF4p5_PDLFFT) {
      symbol_mask = symbol_mask | (1<<symbol_number);
    }
532
    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
533
  } while (symbol_mask != symbol_mask_full);    
534

535
  if (subframe_select(fp,tti_tx) == SF_DL) stop_meas(&ru->rx_fhaul);
536

537 538
  ru->north_in_cnt++;

539
  proc->tti_tx  = tti_tx;
yilmazt's avatar
yilmazt committed
540
  proc->frame_tx= frame_tx;
541

542
  if ((frame_tx == 0)&&(tti_tx == 0)) proc->frame_tx_unwrap += 1024;
543

544
  proc->timestamp_tx = ((((uint64_t)frame_tx + (uint64_t)proc->frame_tx_unwrap) * 10) + (uint64_t)tti_tx) * (uint64_t)fp->samples_per_tti;
545

546
  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,tti_tx);
547 548

  // dump VCD output for first RU in list
549
  if (ru == RC.ru[0]) {
magounak's avatar
magounak committed
550
    /*VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame_tx );
yilmazt's avatar
yilmazt committed
551 552 553
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, tti_tx );*/
    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, tti_tx);
554
  }
555

556 557
  if (ru->feptx_ofdm) ru->feptx_ofdm(ru,frame_tx,tti_tx);
  if (ru->fh_south_out) ru->fh_south_out(ru,frame_tx,tti_tx,proc->timestamp_tx);
558
}
Raymond Knopp's avatar
Raymond Knopp committed
559

560

561 562
void fh_if5_north_out(RU_t *ru)
{
563 564 565 566 567
  RU_proc_t *proc=&ru->proc;
  uint8_t seqno=0;

  /// **** send_IF5 of rxdata to BBU **** ///       
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 );  
568
  send_IF5(ru, proc->timestamp_rx, proc->tti_rx, &seqno, IF5_RRH_GW_UL);
569 570 571
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 );          
}

yilmazt's avatar
yilmazt committed
572

573
// RRU IF4p5 northbound interface (RX)
574 575
void fh_if4p5_north_out(RU_t *ru)
{
576
  RU_proc_t *proc=&ru->proc;
Guy De Souza's avatar
Guy De Souza committed
577
  LTE_DL_FRAME_PARMS *fp = ru->frame_parms;
578
  const int subframe     = proc->tti_rx;
yilmazt's avatar
yilmazt committed
579 580 581 582
  if (ru->idx==0) {
	  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_RX0_RU, proc->tti_rx );
	  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_IF4P5_NORTH_OUT, proc->tti_rx );
	  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_IF4P5_NORTH_OUT, proc->frame_rx );
magounak's avatar
magounak committed
583
  }
584

yilmazt's avatar
yilmazt committed
585
  LOG_D(PHY,"fh_if4p5_north_out: Sending IF4p5_PULFFT SFN.SF %d.%d\n",proc->frame_rx,proc->tti_rx);
586 587
  if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) {
    /// **** in TDD during DL send_IF4 of ULTICK to RCC **** ///
588
    send_IF4p5(ru, proc->frame_rx, proc->tti_rx, IF4p5_PULTICK);
589
    ru->north_out_cnt++;
590 591 592
    return;
  }

593
  start_meas(&ru->tx_fhaul);
594
  send_IF4p5(ru, proc->frame_rx, proc->tti_rx, IF4p5_PULFFT);
595
  ru->north_out_cnt++;
596
  stop_meas(&ru->tx_fhaul);
597
}
598

Wang Tsu-Han's avatar
Wang Tsu-Han committed
599 600
/* add fail safe for late command */
typedef enum {
601 602 603 604 605
  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
606 607 608 609 610 611
} late_control_e;

volatile late_control_e late_control=STATE_BURST_NORMAL;

/* add fail safe for late command end */

yilmazt's avatar
yilmazt committed
612 613
static void *emulatedRF_thread(void *param)
{
614 615 616
  RU_proc_t *proc = (RU_proc_t *) param;
  int microsec = 500; // length of time to sleep, in miliseconds
  struct timespec req = {0};
617
  int numerology = get_softmodem_params()->numerology;
618
  req.tv_sec = 0;
Eurecom's avatar
Eurecom committed
619
  req.tv_nsec = (numerology>0)? ((microsec * 1000L)/numerology):(microsec * 1000L)*2;
620
  cpu_set_t cpuset;
621
  CPU_ZERO(&cpuset);
622 623 624
  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
625 626
  int ret;

627 628 629
  struct sched_param sparam;
  memset(&sparam, 0, sizeof(sparam));
  sparam.sched_priority = sched_get_priority_max(SCHED_FIFO);
630
  policy = SCHED_FIFO ;
631
  pthread_setschedparam(pthread_self(), policy, &sparam);
632
  wait_sync("emulatedRF_thread");
633 634

  while(!oai_exit) {
635
    nanosleep(&req, (struct timespec *)NULL);
636 637

    if(proc->emulate_rf_busy ) {
638 639
      LOG_E(PHY,"rf being delayed in emulated RF\n");
    }
640

641
    proc->emulate_rf_busy = 1;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
642
    AssertFatal((ret=pthread_mutex_lock(&proc->mutex_emulateRF))==0,"mutex_lock returns %d\n",ret);
643 644
    ++proc->instance_cnt_emulateRF;
    pthread_cond_signal(&proc->cond_emulateRF);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
645
    AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_emulateRF))==0,"mutex_unlock returns %d\n",ret);
646
  }
647

648 649 650
  return 0;
}

yilmazt's avatar
yilmazt committed
651

652 653 654 655
void rx_rf(RU_t *ru,
		   int *frame,
		   int *subframe)
{
656
  RU_proc_t *proc = &ru->proc;
Guy De Souza's avatar
Guy De Souza committed
657
  LTE_DL_FRAME_PARMS *fp = ru->frame_parms;
658
  void *rxp[ru->nb_rx];
659
  unsigned int rxs;
Raymond Knopp's avatar
Raymond Knopp committed
660
  int i;
661
  int resynch=0;
662

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

Raymond Knopp's avatar
Raymond Knopp committed
667
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 );
668
  old_ts = proc->timestamp_rx;
669 670

  if(get_softmodem_params()->emulate_rf) {
671 672 673
    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;
674
  } else {
675
    rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
676 677 678 679
                                     &ts,
                                     rxp,
                                     fp->samples_per_tti,
                                     ru->nb_rx);
680
  }
681

Raymond Knopp's avatar
Raymond Knopp committed
682
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
683

684
  ru->south_in_cnt++;
685
  LOG_D(PHY,"south_in_cnt %d\n",ru->south_in_cnt);
686

687
  if (ru->cmd==RU_FRAME_RESYNCH) {
688 689 690
    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;
691 692
    *frame = ru->cmdval;
    ru->cmd=EMPTY;
693
    resynch=1;
694
  }
Raymond Knopp's avatar
Raymond Knopp committed
695
 
696
  proc->timestamp_rx = ts-ru->ts_offset;
697

698 699 700
  //  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) {
701
    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
702 703
    late_control=STATE_BURST_TERMINATE;
  }
704 705

  if (proc->first_rx == 1) {
706
    ru->ts_offset = proc->timestamp_rx;
707
    proc->timestamp_rx = 0;
708 709 710 711 712
  } 
  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;
713
  }
714

715

716
  proc->frame_rx     = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023;
717
  proc->tti_rx  = (proc->timestamp_rx / fp->samples_per_tti)%10;
Raymond Knopp's avatar
Raymond Knopp committed
718 719
  // synchronize first reception to frame 0 subframe 0

720

Raymond Knopp's avatar
Raymond Knopp committed
721
  if (ru->fh_north_asynch_in == NULL) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
722 723
#ifdef PHY_TX_THREAD
  proc->timestamp_phy_tx = proc->timestamp_rx+((sf_ahead-1)*fp->samples_per_tti);
724 725
  proc->subframe_phy_tx  = (proc->tti_rx+(sf_ahead-1))%10;  
  proc->frame_phy_tx     = (proc->tti_rx>(9-(sf_ahead-1))) ? (proc->frame_rx+1)&1023 : proc->frame_rx;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
726 727
#else
  proc->timestamp_tx = proc->timestamp_rx+(sf_ahead*fp->samples_per_tti);
yilmazt's avatar
yilmazt committed
728
  proc->tti_tx       = (proc->tti_rx+sf_ahead)%10;
729
  proc->frame_tx     = (proc->tti_rx>(9-sf_ahead)) ? (proc->frame_rx+1)&1023 : proc->frame_rx;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
730
#endif
731
  //proc->timestamp_tx = proc->timestamp_rx+(sf_ahead*fp->samples_per_tti);
732 733
  //proc->subframe_tx  = (proc->tti_rx+sf_ahead)%10;
  //proc->frame_tx     = (proc->tti_rx>(9-sf_ahead)) ? (proc->frame_rx+1)&1023 : proc->frame_rx;
734
  
735
    LOG_D(PHY,"RU %d/%d TS %llu (off %d), frame %d, subframe %d\n",
yilmazt's avatar
yilmazt committed
736 737 738 739 740 741 742
      ru->idx,
      0,
      (unsigned long long int)proc->timestamp_rx,
      (int)ru->ts_offset,
      proc->frame_rx,
      proc->tti_rx);

743
    LOG_D(PHY,"south_in/rx_rf: RU %d/%d TS %llu (off %d), frame %d, subframe %d\n",
yilmazt's avatar
yilmazt committed
744 745 746 747 748 749
      ru->idx,
      0,
      (unsigned long long int)proc->timestamp_rx,
      (int)ru->ts_offset,
      proc->frame_rx,
      proc->tti_rx);
750

751 752 753
    // 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 );
yilmazt's avatar
yilmazt committed
754
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_RX0_RU, proc->tti_rx );
755
      if (ru->fh_north_asynch_in == NULL) {
yilmazt's avatar
yilmazt committed
756 757
        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_TTI_NUMBER_TX0_RU, proc->tti_rx );
758
      }
Raymond Knopp's avatar
Raymond Knopp committed
759
    }
760
  }
761

Raymond Knopp's avatar
Raymond Knopp committed
762
  if (proc->first_rx == 0) {
763 764
    if (proc->tti_rx != *subframe){
      LOG_E(PHY,"Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->tti_rx %d, subframe %d)\n",(long long unsigned int)proc->timestamp_rx,proc->tti_rx,*subframe);
Raymond Knopp's avatar
Raymond Knopp committed
765 766
      exit_fun("Exiting");
    }
767

Raymond Knopp's avatar
Raymond Knopp committed
768
    if (proc->frame_rx != *frame) {
769
      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
770 771 772 773 774
      exit_fun("Exiting");
    }
  } else {
    proc->first_rx = 0;
    *frame = proc->frame_rx;
775
    *subframe = proc->tti_rx;        
Raymond Knopp's avatar
Raymond Knopp committed
776 777
  }
  
778
  //printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",ru->timestamp_rx,proc->frame_rx,frame,proc->tti_rx,subframe);
Raymond Knopp's avatar
Raymond Knopp committed
779
  
780
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
781 782

  if (rxs != fp->samples_per_tti) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
783 784
#if defined(USRP_REC_PLAY)
    exit_fun("Exiting IQ record/playback");
785
#else
786
    //exit_fun( "problem receiving samples" );
Cedric Roux's avatar
Cedric Roux committed
787
    LOG_E(PHY, "problem receiving samples");
788
#endif
789
  }
Raymond Knopp's avatar
Raymond Knopp committed
790 791 792
}


yilmazt's avatar
yilmazt committed
793 794 795 796 797
void tx_rf(RU_t *ru,
           int frame,
           int subframe,
           uint64_t timestamp)
{
798
  RU_proc_t *proc = &ru->proc;
Guy De Souza's avatar
Guy De Souza committed
799
  LTE_DL_FRAME_PARMS *fp = ru->frame_parms;
800
  void *txp[ru->nb_tx]; 
801 802 803
  unsigned int txs;
  int i;

804 805
  T(T_ENB_PHY_OUTPUT_SIGNAL, T_INT(0), T_INT(0), T_INT(frame), T_INT(subframe),
    T_INT(0), T_BUFFER(&ru->common.txdata[0][subframe * fp->samples_per_tti], fp->samples_per_tti * 4));
806

807 808
  lte_subframe_t SF_type     = subframe_select(fp,subframe%10);
  lte_subframe_t prevSF_type = subframe_select(fp,(subframe+9)%10);
809
  //lte_subframe_t nextSF_type = subframe_select(fp,(subframe+1)%10);
810
  int sf_extension = 0;
magounak's avatar
magounak committed
811
  
812

813 814 815
  if ((SF_type == SF_DL) ||
      (SF_type == SF_S)) {
    int siglen=fp->samples_per_tti,flags=1;
816

817
    if (SF_type == SF_S) {
818 819
      int txsymb = fp->dl_symbols_in_S_subframe+(ru->is_slave==0 ? 1 : 0);
      AssertFatal(txsymb>0,"illegal txsymb %d\n",txsymb);
820 821 822 823 824 825 826
      /* 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.
       */
827
      siglen = (fp->ofdm_symbol_size + fp->nb_prefix_samples0)
828
               + (txsymb - 1) * (fp->ofdm_symbol_size + fp->nb_prefix_samples)
829
               + ru->end_of_burst_delay;
830 831
      flags=3; // end of burst
    }
832

833 834 835
    if (fp->frame_type == TDD &&
        SF_type == SF_DL &&
        prevSF_type == SF_UL) {
836
      flags = 2; // start of burst
837
      sf_extension = ru->sf_extension;
838
    }
839

Wang Tsu-Han's avatar
Wang Tsu-Han committed
840 841
#if defined(__x86_64) || defined(__i386__)
#ifdef __AVX2__
842
    sf_extension = (sf_extension)&0xfffffff8;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
843
#else
844
    sf_extension = (sf_extension)&0xfffffffc;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
845 846
#endif
#elif defined(__arm__)
847
    sf_extension = (sf_extension)&0xfffffffc;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
848
#endif
849

850
    for (i=0; i<ru->nb_tx; i++)
851
      txp[i] = (void*)&ru->common.txdata[i][(subframe*fp->samples_per_tti)-sf_extension];
852

Wang Tsu-Han's avatar
Wang Tsu-Han committed
853
    /* add fail safe for late command */
854
    if(late_control!=STATE_BURST_NORMAL) { //stop burst
Wang Tsu-Han's avatar
Wang Tsu-Han committed
855
      switch (late_control) {
856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880
        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
881 882
      }
    }
883
    /* add fail safe for late command end */
884 885 886
    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_TTI_NUMBER_TX0_RU, subframe);
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp-ru->openair0_cfg.tx_sample_advance)&0xffffffff );
887 888 889
    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,
yilmazt's avatar
yilmazt committed
890 891 892 893 894 895
                                      timestamp+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension,
                                      txp,
                                      siglen+sf_extension,
                                      ru->nb_tx,
                                      flags);

896
    ru->south_out_cnt++;
Raymond Knopp's avatar
Raymond Knopp committed
897
    LOG_D(PHY,"south_out_cnt %d\n",ru->south_out_cnt);
898
    int se = dB_fixed(signal_energy(txp[0],siglen+sf_extension));
magounak's avatar
magounak committed
899

yilmazt's avatar
yilmazt committed
900 901
    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)timestamp, frame, proc->frame_tx_unwrap, subframe);
902
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
903 904 905

    //    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
906 907 908
      late_control=STATE_BURST_TERMINATE;
      LOG_E(PHY,"TX : Timeout (sent %d/%d) state =%d\n",txs, siglen,late_control);
    }
909
  }
910 911 912
}


Raymond Knopp's avatar
Raymond Knopp committed
913 914 915
/*!
 * \brief The Asynchronous RX/TX FH thread of RAU/RCC/eNB/RRU.
 * This handles the RX FH for an asynchronous RRU/UE
916
 * \param param is a \ref L1_proc_t structure which contains the info what to process.
Raymond Knopp's avatar
Raymond Knopp committed
917 918
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
919 920
static void *ru_thread_asynch_rxtx( void *param )
{
Raymond Knopp's avatar
Raymond Knopp committed
921
  static int ru_thread_asynch_rxtx_status;
922
  RU_t *ru         = (RU_t *)param;
923
  RU_proc_t *proc  = &ru->proc;
924
  int subframe=0, frame=0;
925
  thread_top_init("ru_thread_asynch_rxtx",1,870000,1000000,1000000);
Raymond Knopp's avatar
Raymond Knopp committed
926
  // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe
927
  wait_sync("ru_thread_asynch_rxtx");
Raymond Knopp's avatar
Raymond Knopp committed
928
  // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe
Raymond Knopp's avatar
Raymond Knopp committed
929
  LOG_I(PHY, "waiting for devices (ru_thread_asynch_rxtx)\n");
Raymond Knopp's avatar
Raymond Knopp committed
930 931 932

  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
933
  LOG_I(PHY, "devices ok (ru_thread_asynch_rxtx)\n");
Raymond Knopp's avatar
Raymond Knopp committed
934

935 936
  while (!oai_exit) {
    if (oai_exit) break;
Raymond Knopp's avatar
Raymond Knopp committed
937

938
    if (ru->state != RU_RUN) {
Raymond Knopp's avatar
Raymond Knopp committed
939
      subframe=0;
940 941
      frame=0;
      usleep(1000);
942
    }
943 944 945 946 947 948 949
    else {
      if (subframe==9) { 
         subframe=0;
         frame++;
         frame&=1023;
       } else {
         subframe++;
yilmazt's avatar
yilmazt committed
950
      }
951 952


953
      LOG_D(PHY,"ru_thread_asynch_rxtx: Waiting on incoming fronthaul\n");
Raymond Knopp's avatar
Raymond Knopp committed
954

yilmazt's avatar
yilmazt committed
955 956 957 958
      // asynchronous receive from south (Mobipass)
      if (ru->fh_south_asynch_in) {
        ru->fh_south_asynch_in(ru,&frame,&subframe);
      }
959
      // asynchronous receive from north (RRU IF4/IF5)
yilmazt's avatar
yilmazt committed
960 961
      else if (ru->fh_north_asynch_in) {
        if (subframe_select(ru->frame_parms,subframe)!=SF_UL) ru->fh_north_asynch_in(ru,&frame,&subframe);
962
      }
yilmazt's avatar
yilmazt committed
963 964
      else
        AssertFatal(1==0,"Unknown function in ru_thread_asynch_rxtx\n");
965
    }
Raymond Knopp's avatar
Raymond Knopp committed
966 967 968 969 970 971
  }
  ru_thread_asynch_rxtx_status=0;
  return(&ru_thread_asynch_rxtx_status);
}


972 973
void wakeup_slaves(RU_proc_t *proc)
{
yilmazt's avatar
yilmazt committed
974
  int ret;
Raymond Knopp's avatar
Raymond Knopp committed
975
  struct timespec wait;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
976
  int time_ns = 5000000L;
977

yilmazt's avatar
yilmazt committed
978
  for (int i=0; i<proc->num_slaves; i++) {
979
    RU_proc_t *slave_proc = proc->slave_proc[i];
980

Raymond Knopp's avatar
Raymond Knopp committed
981 982
    // 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
983 984
    clock_gettime(CLOCK_REALTIME,&wait);
    wait.tv_nsec += time_ns;
985 986 987 988
    if(wait.tv_nsec >= 1000*1000*1000)
    {
      wait.tv_nsec -= 1000*1000*1000;
      wait.tv_sec  += 1;
Raymond Knopp's avatar
Raymond Knopp committed
989
    }
990
    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);
991

Raymond Knopp's avatar
Raymond Knopp committed
992 993
    int cnt_slave            = ++slave_proc->instance_cnt_FH;
    slave_proc->frame_rx     = proc->frame_rx;
994
    slave_proc->tti_rx  = proc->tti_rx;
Raymond Knopp's avatar
Raymond Knopp committed
995
    slave_proc->timestamp_rx = proc->timestamp_rx;
996
    slave_proc->timestamp_tx = proc->timestamp_tx;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
997
    AssertFatal((ret=pthread_mutex_unlock( &slave_proc->mutex_FH ))==0,"mutex_unlock returns %d\n",ret);
998

Raymond Knopp's avatar
Raymond Knopp committed
999 1000 1001
    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) {
1002
	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
1003 1004
	exit_fun( "ERROR pthread_cond_signal" );
	break;
Raymond Knopp's avatar
Raymond Knopp committed
1005 1006
      }
    } else {
1007
      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
1008 1009
      exit_fun( "FH thread busy" );
      break;
1010
    }
Raymond Knopp's avatar
Raymond Knopp committed
1011 1012 1013
  }
}

yilmazt's avatar
yilmazt committed
1014

Raymond Knopp's avatar
Raymond Knopp committed
1015 1016
/*!
 * \brief The prach receive thread of RU.
1017
 * \param param is a \ref RU_proc_t structure which contains the info what to process.
Raymond Knopp's avatar
Raymond Knopp committed
1018 1019
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
yilmazt's avatar
yilmazt committed
1020 1021
void *ru_thread_prach( void *param )
{
Raymond Knopp's avatar
Raymond Knopp committed
1022
  static int ru_thread_prach_status;
1023 1024
  RU_t *ru        = (RU_t *)param;
  RU_proc_t *proc = (RU_proc_t *)&ru->proc;
Raymond Knopp's avatar
Raymond Knopp committed
1025
  // set default return value
1026
  ru_thread_prach_status = 0;
1027
  thread_top_init("ru_thread_prach",1,500000,1000000,20000000);
1028
  //wait_sync("ru_thread_prach");
Raymond Knopp's avatar
Raymond Knopp committed
1029

1030
  while (RC.ru_mask>0 && ru->function!=eNodeB_3GPP) {
1031
    usleep(1e6);
1032
    LOG_D(PHY,"%s() RACH waiting for RU to be configured\n", __FUNCTION__);
1033
  }
1034

1035 1036
  LOG_I(PHY,"%s() RU configured - RACH processing thread running\n", __FUNCTION__);

Raymond Knopp's avatar
Raymond Knopp committed
1037
  while (!oai_exit) {
1038
    if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break;
1039

1040
    if (oai_exit) break;
1041 1042 1043 1044

    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 1 );

    if (ru->eNB_list[0]) {
1045
      prach_procedures(
1046
        ru->eNB_list[0]
1047
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1048
        ,0
1049
#endif
1050 1051 1052 1053 1054 1055 1056
      );
    } else {
      rx_prach(NULL,
               ru,
               NULL,
               NULL,
               NULL,
yilmazt's avatar
yilmazt committed
1057
               NULL,
1058 1059
               proc->frame_prach,
               0
1060
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1061
               ,0
1062
#endif
yilmazt's avatar
yilmazt committed
1063
               );
1064 1065 1066 1067
    }

    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 );

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

1071 1072 1073 1074 1075
  LOG_I(PHY, "Exiting RU thread PRACH\n");
  ru_thread_prach_status = 0;
  return &ru_thread_prach_status;
}

1076
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1077
void *ru_thread_prach_br( void *param ) {
1078
  static int ru_thread_prach_status;
1079 1080
  RU_t *ru        = (RU_t *)param;
  RU_proc_t *proc = (RU_proc_t *)&ru->proc;
1081 1082
  // set default return value
  ru_thread_prach_status = 0;
1083
  thread_top_init("ru_thread_prach_br",1,500000,1000000,20000000);
1084
  //wait_sync("ru_thread_prach_br");
1085 1086 1087

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

1089
    if (oai_exit) break;
1090

1091
    rx_prach(NULL,
1092 1093
             ru,
             NULL,
1094 1095
             NULL,
             NULL,
yilmazt's avatar
yilmazt committed
1096
             NULL,
1097 1098
             proc->frame_prach_br,
             0,
1099 1100
             1);

1101 1102 1103 1104
    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");
1105 1106
  ru_thread_prach_status = 0;
  return &ru_thread_prach_status;
Raymond Knopp's avatar
Raymond Knopp committed
1107
}
1108
#endif
Raymond Knopp's avatar
Raymond Knopp committed
1109

yilmazt's avatar
yilmazt committed
1110 1111 1112

int wakeup_synch(RU_t *ru)
{
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1113
  int ret;
1114
  struct timespec wait;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1115
  int time_ns = 5000000L;
Raymond Knopp's avatar
Raymond Knopp committed
1116

1117
  // wake up synch thread
Raymond Knopp's avatar
Raymond Knopp committed
1118
  // 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
1119 1120
  clock_gettime(CLOCK_REALTIME,&wait);
  wait.tv_nsec += time_ns;
1121 1122 1123 1124
  if(wait.tv_nsec >= 1000*1000*1000)
  {
    wait.tv_nsec -= 1000*1000*1000;
    wait.tv_sec  += 1;
1125
  }
1126
  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 );
1127

1128
  ++ru->proc.instance_cnt_synch;
1129

1130 1131 1132 1133 1134 1135 1136
  // 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
1137
  AssertFatal((ret=pthread_mutex_unlock( &ru->proc.mutex_synch ))==0,"mutex_unlock returns %d\n",ret);
1138 1139 1140
  return(0);
}

yilmazt's avatar
yilmazt committed
1141

1142 1143
void do_ru_synch(RU_t *ru)
{
Guy De Souza's avatar
Guy De Souza committed
1144
  LTE_DL_FRAME_PARMS *fp  = ru->frame_parms;
1145
  RU_proc_t *proc         = &ru->proc;
yilmazt's avatar
yilmazt committed
1146
  int rxs, ic, ret, i;
Raymond Knopp's avatar
Raymond Knopp committed
1147 1148 1149 1150
  void *rxp[2],*rxp2[2];
  int32_t dummy_rx[ru->nb_rx][fp->samples_per_tti] __attribute__((aligned(32)));

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

  double temp_freq1 = ru->rfdevice.openair0_cfg->rx_freq[0];
1155 1156

  for (i=0; i<4; i++) {
Raymond Knopp's avatar
Raymond Knopp committed
1157 1158 1159
    ru->rfdevice.openair0_cfg->rx_freq[i] = ru->rfdevice.openair0_cfg->tx_freq[i];
    ru->rfdevice.openair0_cfg->tx_freq[i] = temp_freq1;
  }
1160

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

Raymond Knopp's avatar
Raymond Knopp committed
1163 1164 1165
  while ((ru->in_synch ==0)&&(!oai_exit)) {
    // read in frame
    rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
1166 1167 1168 1169 1170
                                     &(proc->timestamp_rx),
                                     rxp,
                                     fp->samples_per_tti*10,
                                     ru->nb_rx);

1171
    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
1172 1173 1174
    // wakeup synchronization processing thread
    wakeup_synch(ru);
    ic=0;
1175

Raymond Knopp's avatar
Raymond Knopp committed
1176
    while ((ic>=0)&&(!oai_exit)) {
1177
      // continuously read in frames, 1ms at a time,
Raymond Knopp's avatar
Raymond Knopp committed
1178
      // until we are done with the synchronization procedure
1179
      for (i=0; i<ru->nb_rx; i++)
1180 1181 1182 1183 1184 1185 1186 1187 1188
        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
1189
      AssertFatal((ret=pthread_mutex_lock(&ru->proc.mutex_synch))==0,"mutex_lock returns %d\n",ret);
1190
      ic = ru->proc.instance_cnt_synch;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1191
      AssertFatal((ret=pthread_mutex_unlock(&ru->proc.mutex_synch))==0,"mutex_unlock returns %d\n",ret);
Raymond Knopp's avatar
Raymond Knopp committed
1192 1193
    } // ic>=0
  } // in_synch==0
1194 1195

  // read in rx_offset samples
Raymond Knopp's avatar
Raymond Knopp committed
1196 1197 1198 1199 1200
  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,
1201
				   ru->nb_rx);
1202 1203
  // Verification of synchronization procedure
  ru->state = RU_CHECK_SYNC;
Younes's avatar
Younes committed
1204

1205
  LOG_I(PHY,"Exiting synch routine\n");
Raymond Knopp's avatar
Raymond Knopp committed
1206
}
1207

Raymond Knopp's avatar
Raymond Knopp committed
1208

yilmazt's avatar
yilmazt committed
1209 1210 1211 1212
int check_sync(RU_t *ru,
               RU_t *ru_master,
               int subframe)
{
1213 1214 1215
	if (fabs(ru_master->proc.t[subframe].tv_nsec - ru->proc.t[subframe].tv_nsec) > 500000)
		return 0;
	return 1;
Raymond Knopp's avatar
Raymond Knopp committed
1216 1217
}

1218

1219 1220
void wakeup_L1s(RU_t *ru)
{
1221
  PHY_VARS_eNB **eNB_list = ru->eNB_list;
yilmazt's avatar
yilmazt committed
1222
  LOG_D(PHY,"wakeup_L1s (num %d) for RU %d (%d.%d)\n", ru->num_eNB, ru->idx, ru->proc.frame_rx,ru->proc.tti_rx);
1223

yilmazt's avatar
yilmazt committed
1224 1225
  PHY_VARS_eNB *eNB = eNB_list[0];
  L1_proc_t *proc   = &eNB->proc;
1226
  struct timespec t;
yilmazt's avatar
yilmazt committed
1227
  LOG_D(PHY,"wakeup_L1s (num %d) for RU %d ru->eNB_top:%p\n", ru->num_eNB, ru->idx, ru->eNB_top);
1228

1229 1230 1231
  // call eNB function directly
  char string[20];
  sprintf(string,"Incoming RU %d",ru->idx);
1232

yilmazt's avatar
yilmazt committed
1233 1234
  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.tti_rx);
1235
  
1236
  AssertFatal(0==pthread_mutex_lock(&proc->mutex_RU),"");
yilmazt's avatar
yilmazt committed
1237
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LOCK_MUTEX_RU+ru->idx, 1);
1238 1239 1240 1241
  
  //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
1242
  //    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_WAKEUP_L1S_RU+ru->idx, ru->proc.subframe_rx);
yilmazt's avatar
yilmazt committed
1243
  clock_gettime(CLOCK_MONOTONIC,&ru->proc.t[ru->proc.tti_rx]);
1244
  
yilmazt's avatar
yilmazt committed
1245
  if (proc->RU_mask[ru->proc.tti_rx] == 0) {
1246
    //clock_gettime(CLOCK_MONOTONIC,&proc->t[ru->proc.subframe_rx]);
yilmazt's avatar
yilmazt committed
1247
    proc->t[ru->proc.tti_rx] = ru->proc.t[ru->proc.tti_rx];
1248
    //start_meas(&proc->ru_arrival_time);
yilmazt's avatar
yilmazt committed
1249
    LOG_D(PHY,"RU %d starting timer for frame %d subframe %d\n", ru->idx, ru->proc.frame_rx, ru->proc.tti_rx);
1250 1251
  }
  
yilmazt's avatar
yilmazt committed
1252 1253 1254 1255
  for (int i=0; i<eNB->num_RU; i++) {
    if (eNB->RU_list[i]->wait_cnt==1 && ru->proc.tti_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.tti_rx, ru_states[eNB->RU_list[i]->state]);
1256 1257
    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);
yilmazt's avatar
yilmazt committed
1258 1259 1260
      proc->RU_mask[ru->proc.tti_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.tti_rx] |= (1<<i);
1261
    }
1262
    //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);
yilmazt's avatar
yilmazt committed
1263 1264 1265 1266 1267 1268 1269 1270 1271
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_MASK_RU, proc->RU_mask[ru->proc.tti_rx]);
    if (ru->is_slave == 0 && ( (proc->RU_mask[ru->proc.tti_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.tti_rx)  == 0)
        LOG_E(PHY,"RU %d is not SYNC, subframe %d, time  %f this is master\n",
        		eNB->RU_list[i]->idx, ru->proc.tti_rx, fabs(eNB->RU_list[i]->proc.t[ru->proc.tti_rx].tv_nsec - eNB->RU_list[0]->proc.t[ru->proc.tti_rx].tv_nsec));
    } else if (ru->is_slave == 1 && ru->state == RU_RUN && ( (proc->RU_mask[ru->proc.tti_rx]&(1<<0)) == 1)) { // master already received. TODO: we assume that RU0 is master.
      if (check_sync(ru,eNB->RU_list[0],ru->proc.tti_rx)  == 0)
        LOG_E(PHY,"RU %d is not SYNC time, subframe %d, time  %f\n",
        		ru->idx, ru->proc.tti_rx, fabs(ru->proc.t[ru->proc.tti_rx].tv_nsec - eNB->RU_list[0]->proc.t[ru->proc.tti_rx].tv_nsec));
1272
    }
1273 1274 1275 1276
  }
  //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);
  
yilmazt's avatar
yilmazt committed
1277 1278
  if (proc->RU_mask[ru->proc.tti_rx] == (1<<eNB->num_RU)-1) { // all RUs have provided their information so continue on and wakeup eNB top
    LOG_D(PHY,"ru_mask is %d \n ", proc->RU_mask[ru->proc.tti_rx]);
1279
    LOG_D(PHY,"the number of RU is %d, the current ru is RU %d \n ", (1<<eNB->num_RU)-1, ru->idx);
yilmazt's avatar
yilmazt committed
1280 1281 1282 1283
    LOG_D(PHY,"ru->proc.subframe_rx is %d \n", ru->proc.tti_rx);
    LOG_D(PHY,"Reseting mask frame %d, subframe %d, this is RU %d\n",ru->proc.frame_rx, ru->proc.tti_rx, ru->idx);
    proc->RU_mask[ru->proc.tti_rx] = 0;
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_MASK_RU, proc->RU_mask[ru->proc.tti_rx]);
1284 1285
    clock_gettime(CLOCK_MONOTONIC,&t);
    //stop_meas(&proc->ru_arrival_time);
1286
    /*    AssertFatal(t.tv_nsec < proc->t[ru->proc.subframe_rx].tv_nsec+5000000,
1287 1288
		"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);
1289
    */
1290 1291 1292 1293 1294 1295
    // 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
yilmazt's avatar
yilmazt committed
1296
    LOG_D(PHY,"RU %d wakeup eNB top for subframe %d\n", ru->idx, ru->proc.tti_rx);
1297
    if (ru->wait_cnt == 0) {
yilmazt's avatar
yilmazt committed
1298 1299 1300 1301 1302 1303 1304 1305 1306
      if (ru->num_eNB==1 && ru->eNB_top!=0 && get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD) {
        LOG_D(PHY,"RU %d Call eNB_top\n", ru->idx);
        ru->eNB_top(eNB_list[0], proc->frame_rx, proc->subframe_rx, string, ru);
      } else {
        for (int i=0; i<ru->num_eNB; i++) {
          LOG_D(PHY,"ru->wakeup_rxtx:%p\n", ru->wakeup_rxtx);
          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.tti_rx);
        }
1307
      }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1308
    }
1309
    /*
1310
      AssertFatal(0==pthread_mutex_lock(&ruproc->mutex_eNBs),"");
1311
      LOG_D(PHY,"RU %d sending signal to unlock waiting ru_threads\n", ru->idx);
1312 1313 1314
      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),"");
1315
    */
yilmazt's avatar
yilmazt committed
1316 1317
  }
  else { // not all RUs have provided their information
magounak's avatar
magounak committed
1318
    AssertFatal(0==pthread_mutex_unlock(&proc->mutex_RU),"");
magounak's avatar
magounak committed
1319
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_LOCK_MUTEX_RU+ru->idx, 0 );
1320
  }
1321 1322 1323
//      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);
yilmazt's avatar
yilmazt committed
1324
  ru->proc.emulate_rf_busy = 0;
1325 1326 1327
}


1328 1329
static inline int wakeup_prach_ru(RU_t *ru)
{
1330
  struct timespec wait;
yilmazt's avatar
yilmazt committed
1331
  int time_ns = 5000000L, ret;
1332

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1333 1334
  clock_gettime(CLOCK_REALTIME,&wait);
  wait.tv_nsec += time_ns;
1335 1336 1337 1338
  if(wait.tv_nsec >= 1000*1000*1000)
  {
    wait.tv_nsec -= 1000*1000*1000;
    wait.tv_sec  += 1;
1339
  }
1340 1341
  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);

1342

1343 1344 1345
  if (ru->proc.instance_cnt_prach==-1) {
    ++ru->proc.instance_cnt_prach;
    ru->proc.frame_prach    = ru->proc.frame_rx;
1346
    ru->proc.subframe_prach = ru->proc.tti_rx;
1347

1348
    // DJP - think prach_procedures() is looking at eNB frame_prach
1349 1350
    if (ru->eNB_list[0]) {
      ru->eNB_list[0]->proc.frame_prach = ru->proc.frame_rx;
1351
      ru->eNB_list[0]->proc.subframe_prach = ru->proc.tti_rx;
1352
    }
1353

Raymond Knopp's avatar
Raymond Knopp committed
1354
    LOG_D(PHY,"RU %d: waking up PRACH thread\n",ru->idx);
1355 1356
    // 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");
1357
  } else LOG_W(PHY,"RU prach thread busy, skipping\n");
1358

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1359
  AssertFatal((ret=pthread_mutex_unlock( &ru->proc.mutex_prach ))==0,"mutex_unlock returns %d\n",ret);
1360 1361 1362
  return(0);
}

1363
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1364
inline int wakeup_prach_ru_br(RU_t *ru) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1365
  int ret;
1366
  struct timespec wait;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1367
  int time_ns = 5000000L;
1368

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1369 1370 1371

  clock_gettime(CLOCK_REALTIME,&wait);
  wait.tv_nsec += time_ns;
1372 1373 1374 1375
  if(wait.tv_nsec >= 1000*1000*1000)
  {
    wait.tv_nsec -= 1000*1000*1000;
    wait.tv_sec  += 1;
1376
  }
1377
  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);
1378

1379

1380 1381 1382
  if (ru->proc.instance_cnt_prach_br==-1) {
    ++ru->proc.instance_cnt_prach_br;
    ru->proc.frame_prach_br    = ru->proc.frame_rx;
1383
    ru->proc.subframe_prach_br = ru->proc.tti_rx;
1384 1385 1386 1387

    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");
1388
  } else LOG_W(PHY,"RU prach thread busy, skipping\n");
1389

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1390
  AssertFatal((ret=pthread_mutex_unlock( &ru->proc.mutex_prach_br ))==0,"mutex_unlock returns %d\n",ret);
1391 1392 1393 1394
  return(0);
}
#endif

yilmazt's avatar
yilmazt committed
1395

Raymond Knopp's avatar
Raymond Knopp committed
1396
// this is for RU with local RF unit
1397 1398 1399
void fill_rf_config(RU_t *ru,
		            char *rf_config_file)
{
Raymond Knopp's avatar
Raymond Knopp committed
1400
  int i;
Guy De Souza's avatar
Guy De Souza committed
1401
  LTE_DL_FRAME_PARMS *fp   = ru->frame_parms;
Raymond Knopp's avatar
Raymond Knopp committed
1402
  openair0_config_t *cfg   = &ru->openair0_cfg;
1403
  //printf("////////////////numerology in config = %d\n",numerology);
1404
  int numerology = get_softmodem_params()->numerology;
Raymond Knopp's avatar
Raymond Knopp committed
1405 1406

  if(fp->N_RB_DL == 100) {
1407
    if(numerology == 0) {
1408 1409
      if (fp->threequarter_fs) {
        cfg->sample_rate=23.04e6;
1410
        cfg->samples_per_frame = 230400;
1411 1412
        cfg->tx_bw = 10e6;
        cfg->rx_bw = 10e6;
1413
      } else {
1414
        cfg->sample_rate=30.72e6;
1415
        cfg->samples_per_frame = 307200;
1416 1417 1418
        cfg->tx_bw = 10e6;
        cfg->rx_bw = 10e6;
      }
1419 1420 1421
    } else if(numerology == 1) {
      cfg->sample_rate=61.44e6;
      cfg->samples_per_frame = 307200;
1422 1423
      cfg->tx_bw = 20e6;
      cfg->rx_bw = 20e6;
1424 1425 1426
    } else if(numerology == 2) {
      cfg->sample_rate=122.88e6;
      cfg->samples_per_frame = 307200;
1427 1428
      cfg->tx_bw = 40e6;
      cfg->rx_bw = 40e6;
1429 1430 1431 1432
    } 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
1433 1434
      cfg->tx_bw = 10e6;
      cfg->rx_bw = 10e6;
1435
    }
Raymond Knopp's avatar
Raymond Knopp committed
1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450
  } 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;
1451
  } else AssertFatal(1==0,"Unknown N_RB_DL %d\n",fp->N_RB_DL);
Raymond Knopp's avatar
Raymond Knopp committed
1452

1453

Raymond Knopp's avatar
Raymond Knopp committed
1454 1455 1456 1457 1458 1459 1460 1461 1462
  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;
1463
  cfg->clock_source=get_softmodem_params()->clock_source;
1464

Raymond Knopp's avatar
Raymond Knopp committed
1465 1466 1467
  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
1468 1469
    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
1470 1471
    cfg->configFilename = rf_config_file;
    printf("channel %d, Setting tx_gain offset %f, rx_gain offset %f, tx_freq %f, rx_freq %f\n",
1472 1473 1474 1475
           i, cfg->tx_gain[i],
           cfg->rx_gain[i],
           cfg->tx_freq[i],
           cfg->rx_freq[i]);
Raymond Knopp's avatar
Raymond Knopp committed
1476 1477 1478
  }
}

yilmazt's avatar
yilmazt committed
1479

Raymond Knopp's avatar
Raymond Knopp committed
1480 1481 1482 1483
/* 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. */
yilmazt's avatar
yilmazt committed
1484 1485
int setup_RU_buffers(RU_t *ru)
{
1486
  int i,j;
Raymond Knopp's avatar
Raymond Knopp committed
1487 1488 1489
  int card,ant;
  //uint16_t N_TA_offset = 0;
  LTE_DL_FRAME_PARMS *frame_parms;
1490

Raymond Knopp's avatar
Raymond Knopp committed
1491
  if (ru) {
Guy De Souza's avatar
Guy De Souza committed
1492
    frame_parms = ru->frame_parms;
Raymond Knopp's avatar
Raymond Knopp committed
1493 1494
    printf("setup_RU_buffers: frame_parms = %p\n",frame_parms);
  } else {
1495
    printf("RU not initialized (NULL pointer)\n");
Raymond Knopp's avatar
Raymond Knopp committed
1496 1497
    return(-1);
  }
1498

1499 1500 1501 1502
  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;
1503

1504 1505 1506 1507 1508
    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;
1509 1510

    if      (frame_parms->N_RB_DL == 100) /* no scaling to do */;
1511 1512 1513 1514 1515 1516 1517 1518 1519 1520
    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);
    }
1521
  } else {
1522
    ru->N_TA_offset = 0;
1523
    ru->sf_extension = 0;
1524
    ru->end_of_burst_delay = 0;
1525 1526
  }

Raymond Knopp's avatar
Raymond Knopp committed
1527 1528 1529 1530 1531 1532 1533 1534 1535
  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]);
1536

Raymond Knopp's avatar
Raymond Knopp committed
1537
      for (j=0; j<16; j++) {
1538 1539
        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
1540 1541
      }
    }
1542

Raymond Knopp's avatar
Raymond Knopp committed
1543 1544 1545 1546 1547 1548 1549
    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]);
1550

Raymond Knopp's avatar
Raymond Knopp committed
1551
      for (j=0; j<16; j++) {
1552 1553
        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
1554 1555
      }
    }
1556
  } else { // not memory-mapped DMA
Raymond Knopp's avatar
Raymond Knopp committed
1557 1558
    //nothing to do, everything already allocated in lte_init
  }
1559

Raymond Knopp's avatar
Raymond Knopp committed
1560 1561 1562
  return(0);
}

1563

1564 1565 1566
static void *ru_stats_thread(void *param)
{
  RU_t *ru = (RU_t *)param;
1567
  wait_sync("ru_stats_thread");
1568
  
1569
  while (!oai_exit) {
1570 1571 1572 1573 1574 1575
    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) {
1576 1577 1578 1579
	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);
1580
      }
1581 1582 1583
      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);
      
1584
    }
1585
  }
1586
  
1587
  return(NULL);
1588 1589
}

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1590
#ifdef PHY_TX_THREAD
1591 1592 1593
  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
1594 1595
#endif

yilmazt's avatar
yilmazt committed
1596

1597 1598
static void* ru_thread_tx( void* param )
{
1599 1600
  RU_t *ru         = (RU_t*)param;
  RU_proc_t *proc  = &ru->proc;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
1601
  LTE_DL_FRAME_PARMS *fp = ru->frame_parms;
1602
  PHY_VARS_eNB *eNB;
1603 1604
  L1_proc_t *eNB_proc;
  L1_rxtx_proc_t *L1_proc;
1605 1606
  cpu_set_t cpuset;
  CPU_ZERO(&cpuset);
1607
  char filename[256];
1608

1609 1610 1611
  thread_top_init("ru_thread_tx",1,400000,500000,500000);
  //CPU_SET(5, &cpuset);
  //pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
1612
  //wait_sync("ru_thread_tx");
1613
  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
1614
  int ret;
1615

1616 1617
  while (!oai_exit) {
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_CPUID_RU_THREAD_TX,sched_getcpu());
1618

1619
    if (oai_exit) break;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1620

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

1625
    LOG_D(PHY,"ru_thread_tx: TX in %d.%d\n",ru->proc.frame_tx,ru->proc.tti_tx);
1626

WANG Tsu-Han's avatar
WANG Tsu-Han committed
1627
    if (oai_exit) break;
1628

1629
    // do TX front-end processing if needed (precoding and/or IDFTs)
1630
    if (ru->feptx_prec) ru->feptx_prec(ru,proc->frame_tx,proc->tti_tx);
1631
  	  
1632
    // do OFDM if needed
1633
    if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,proc->frame_tx,proc->tti_tx);
1634
    if(!(get_softmodem_params()->emulate_rf)) { //if(!emulate_rf){
1635
      // do outgoing fronthaul (south) if needed
1636
      if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,proc->frame_tx,proc->tti_tx,proc->timestamp_tx);
1637 1638
  	      
      if (ru->fh_north_out) ru->fh_north_out(ru);
1639 1640
    }
    else {
1641
      for (int i=0; i<ru->nb_tx; i++) {
yilmazt's avatar
yilmazt committed
1642 1643 1644 1645 1646 1647 1648 1649
        if(proc->frame_tx == 2) {
          sprintf(filename,"txdataF%d_frame%d_sf%d.m",i,proc->frame_tx,proc->tti_tx);
          LOG_M(filename,"txdataF_frame",ru->common.txdataF_BF[i],fp->symbols_per_tti*fp->ofdm_symbol_size, 1, 1);
        }
        if(proc->frame_tx == 2 && proc->tti_tx==0) {
          sprintf(filename,"txdata%d_frame%d.m",i,proc->frame_tx);
          LOG_M(filename,"txdata_frame",ru->common.txdata[i],fp->samples_per_tti*10, 1, 1);
        }
1650 1651 1652
      }
    }

yilmazt's avatar
yilmazt committed
1653
    LOG_D(PHY,"ru_thread_tx: releasing RU TX in %d.%d\n",proc->frame_tx,proc->tti_tx);
1654
    release_thread(&proc->mutex_eNBs,&proc->instance_cnt_eNBs,"ru_thread_tx");
1655 1656

    for(int i = 0; i<ru->num_eNB; i++) {
1657 1658 1659
      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;
1660

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1661
      AssertFatal((ret=pthread_mutex_lock(&eNB_proc->mutex_RU_tx))==0,"mutex_lock returns %d\n",ret);
1662
      for (int j=0; j<eNB->num_RU; j++) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1663
        if (ru == eNB->RU_list[j]) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1664
          if ((eNB_proc->RU_mask_tx&(1<<j)) > 0)
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1665
            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",
1666 1667
                  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
1668
          eNB_proc->RU_mask_tx |= (1<<j);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1669
        }
1670
        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)){
yilmazt's avatar
yilmazt committed
1671
		  eNB_proc->RU_mask_tx |= (1<<j);
1672
        }
yilmazt's avatar
yilmazt committed
1673
	    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
1674 1675
      }
      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
1676
      	//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
1677
        AssertFatal((ret=pthread_mutex_unlock(&eNB_proc->mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret);
1678
      } else { // all RUs TX are finished so send the ready signal to eNB processing
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1679
        eNB_proc->RU_mask_tx = 0;
yilmazt's avatar
yilmazt committed
1680
        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
1681 1682
        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
1683
        L1_proc->instance_cnt_RUs = 0;
1684

yilmazt's avatar
yilmazt committed
1685
        LOG_D(PHY,"ru_thread_tx: Signaling RU TX done in %d.%d\n",proc->frame_tx,proc->tti_tx);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1686
        // the thread can now be woken up
Raymond Knopp's avatar
Raymond Knopp committed
1687
        LOG_D(PHY,"ru_thread_tx: clearing mask and Waking up L1 thread\n"); 
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1688 1689 1690 1691
        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" );
        }
1692

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1693
        AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex_RUs))==0,"mutex_unlock returns %d\n",ret);
1694
      }
1695
    }
magounak's avatar
magounak committed
1696
    //printf("ru_thread_tx: Frame %d, Subframe %d: RU %d done (wait_cnt %d),RU_mask_tx %d\n",
yilmazt's avatar
yilmazt committed
1697
    //eNB_proc->frame_rx,eNB_proc->subframe_rx,ru->idx,ru->wait_cnt,eNB_proc->RU_mask_tx);
1698
  }
1699

1700
  release_thread(&proc->mutex_FH1,&proc->instance_cnt_FH1,"ru_thread_tx");
1701 1702 1703
  return 0;
}

yilmazt's avatar
yilmazt committed
1704

1705 1706
static void *ru_thread( void *param )
{
1707
  RU_t               *ru      = (RU_t *)param;
1708
  RU_proc_t          *proc    = &ru->proc;
yilmazt's avatar
yilmazt committed
1709 1710 1711 1712
  int subframe = 9;
  int frame = 1023;
  int resynch_done = 0;
  int ret;
1713 1714
  cpu_set_t cpuset;
  CPU_ZERO(&cpuset);
Florian Kaltenberger's avatar
Florian Kaltenberger committed
1715
  char filename[256];
Raymond Knopp's avatar
Raymond Knopp committed
1716 1717

  // set default return value
Raymond Knopp's avatar
Raymond Knopp committed
1718

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1719 1720 1721
#if defined(PRE_SCD_THREAD)
  dlsch_ue_select_tbl_in_use = 1;
#endif
Raymond Knopp's avatar
Raymond Knopp committed
1722
  // set default return value
1723
  thread_top_init("ru_thread",1,400000,500000,500000);
Raymond Knopp's avatar
Raymond Knopp committed
1724

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1725 1726
  //CPU_SET(1, &cpuset);
  //pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
1727 1728
  pthread_setname_np( pthread_self(),"ru thread");
  LOG_I(PHY,"thread ru created id=%ld\n", syscall(__NR_gettid));
1729
  LOG_I(PHY,"Starting RU %d (%s,%s),\n",ru->idx, NB_functions[ru->function], NB_timing[ru->if_timing]);
1730

1731
  if(get_softmodem_params()->emulate_rf) {
1732
    fill_rf_config(ru,ru->rf_config_file);
1733
    init_frame_parms(ru->frame_parms,1);
1734
    phy_init_RU(ru);
Raymond Knopp's avatar
Raymond Knopp committed
1735
    
1736
    if (setup_RU_buffers(ru)!=0) {
1737 1738
      printf("Exiting, cannot initialize RU Buffers\n");
      exit(-1);
1739
    }
Raymond Knopp's avatar
Raymond Knopp committed
1740
    
1741
    LOG_I(PHY, "Signaling main thread that RU %d is ready\n",ru->idx);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1742
    AssertFatal((ret=pthread_mutex_lock(&RC.ru_mutex))==0,"mutex_lock returns %d\n",ret);
1743 1744
    RC.ru_mask &= ~(1<<ru->idx);
    pthread_cond_signal(&RC.ru_cond);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1745
    AssertFatal((ret=pthread_mutex_unlock(&RC.ru_mutex))==0,"mutex_unlock returns %d\n",ret);
Raymond Knopp's avatar
Raymond Knopp committed
1746
    ru->state = RU_RUN;
1747
  }
Raymond Knopp's avatar
Raymond Knopp committed
1748
  else if (ru->has_ctrl_prt == 0){
1749 1750
    // There is no control port: start everything here
    LOG_I(PHY, "RU %d has not ctrl port\n",ru->idx);
yilmazt's avatar
yilmazt committed
1751
    if (ru->if_south == LOCAL_RF) {
1752
      fill_rf_config(ru,ru->rf_config_file);
1753
      init_frame_parms(ru->frame_parms,1);
yilmazt's avatar
yilmazt committed
1754
      ru->frame_parms->nb_antennas_rx = ru->nb_rx;
1755
      phy_init_RU(ru);
1756
      
1757
      openair0_device_load(&ru->rfdevice,&ru->openair0_cfg);
1758 1759
      
      if (setup_RU_buffers(ru)!=0) {
yilmazt's avatar
yilmazt committed
1760 1761
        printf("Exiting, cannot initialize RU Buffers\n");
        exit(-1);
1762
      }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1763
      AssertFatal((ret=pthread_mutex_lock(&RC.ru_mutex))==0,"mutex_lock returns %d\n",ret);
1764 1765
      RC.ru_mask &= ~(1<<ru->idx);
      pthread_cond_signal(&RC.ru_cond);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1766
      AssertFatal((ret=pthread_mutex_unlock(&RC.ru_mutex))==0,"mutex_unlock returns %d\n",ret);
1767
    }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1768
    AssertFatal((ret=pthread_mutex_lock(&RC.ru_mutex))==0,"mutex_lock returns %d\n",ret);
1769 1770
    RC.ru_mask &= ~(1<<ru->idx);
    pthread_cond_signal(&RC.ru_cond);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1771
    AssertFatal((ret=pthread_mutex_unlock(&RC.ru_mutex))==0,"mutex_unlock returns %d\n",ret);
1772 1773
    
    ru->state = RU_RUN;
1774
  }
Raymond Knopp's avatar
Raymond Knopp committed
1775
  
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1776
  AssertFatal((ret=pthread_mutex_lock(&proc->mutex_FH1))==0,"mutex_lock returns %d\n",ret);
1777 1778
  proc->instance_cnt_FH1 = 0;
  pthread_cond_signal(&proc->cond_FH1);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1779
  AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_FH1))==0,"mutex_unlock returns %d\n",ret);
1780

Raymond Knopp's avatar
Raymond Knopp committed
1781
  while (!oai_exit) {
Raymond Knopp's avatar
Raymond Knopp committed
1782
    
1783
    if (ru->if_south != LOCAL_RF && ru->is_slave==1) {
Raymond Knopp's avatar
Raymond Knopp committed
1784
      ru->wait_cnt = 100;
1785 1786
    }
    else { 
Raymond Knopp's avatar
Raymond Knopp committed
1787 1788
      ru->wait_cnt = 0;
      ru->wait_check = 0;
1789
    }
Raymond Knopp's avatar
Raymond Knopp committed
1790 1791
    
    
Raymond Knopp's avatar
Raymond Knopp committed
1792 1793 1794 1795 1796
    // 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
1797
    
1798 1799 1800 1801 1802
    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) {
yilmazt's avatar
yilmazt committed
1803 1804 1805
        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);
1806 1807 1808
      }
      else LOG_D(PHY,"RU %d no rf device\n",ru->idx);
    }
1809 1810
    // if an asnych_rxtx thread exists
    // wakeup the thread because the devices are ready at this point
Raymond Knopp's avatar
Raymond Knopp committed
1811
    
1812
    if ((ru->fh_south_asynch_in)||(ru->fh_north_asynch_in)) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1813
      AssertFatal((ret=pthread_mutex_lock(&proc->mutex_asynch_rxtx))==0,"mutex_lock returns %d\n",ret);
1814 1815
      proc->instance_cnt_asynch_rxtx=0;
      pthread_cond_signal(&proc->cond_asynch_rxtx);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1816
      AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_asynch_rxtx))==0,"mutex_unlock returns %d\n",ret);
1817
    } else LOG_D(PHY,"RU %d no asynch_south interface\n",ru->idx);
Raymond Knopp's avatar
Raymond Knopp committed
1818
    
1819
    // if this is a slave RRU, try to synchronize on the DL frequency
Raymond Knopp's avatar
Raymond Knopp committed
1820
    if ((ru->is_slave == 1) && (ru->if_south == LOCAL_RF)) do_ru_synch(ru);
Raymond Knopp's avatar
Raymond Knopp committed
1821
    
1822
    LOG_D(PHY,"Starting steady-state operation\n");
Raymond Knopp's avatar
Raymond Knopp committed
1823
    // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices
1824
    while (ru->state == RU_RUN || ru->state == RU_CHECK_SYNC) {
Raymond Knopp's avatar
Raymond Knopp committed
1825 1826
      // 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
1827 1828 1829 1830
      if (subframe==9) {
        subframe=0;
        frame++;
        frame&=1023;
1831
      } else {
Raymond Knopp's avatar
Raymond Knopp committed
1832
        subframe++;
1833
      }
Raymond Knopp's avatar
Raymond Knopp committed
1834
      
Raymond Knopp's avatar
Raymond Knopp committed
1835
      // synchronization on input FH interface, acquire signals/data and block
1836
      if (ru->fh_south_in) ru->fh_south_in(ru,&frame,&subframe);
Raymond Knopp's avatar
Raymond Knopp committed
1837
      else AssertFatal(1==0, "No fronthaul interface at south port");
Raymond Knopp's avatar
Raymond Knopp committed
1838
      
1839 1840
#ifdef PHY_TX_THREAD
      if(first_phy_tx == 0)
1841
	{ 
1842 1843
	  phy_tx_end = 0;
	  phy_tx_txdataF_end = 0;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1844 1845
          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);

1846 1847 1848 1849 1850 1851 1852 1853 1854
	  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
1855
          AssertFatal((ret=pthread_mutex_unlock( &ru->proc.mutex_phy_tx ))==0,"mutex_unlock returns %d\n",ret);
1856
	} else { 
1857 1858 1859 1860
        phy_tx_end = 1;
        phy_tx_txdataF_end = 1;
      }
      first_phy_tx = 0;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1861
#endif
1862
      
Raymond Knopp's avatar
Raymond Knopp committed
1863 1864 1865 1866 1867 1868
      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;
yilmazt's avatar
yilmazt committed
1869
      } else if (ru->cmd == STOP_RU) {
Raymond Knopp's avatar
Raymond Knopp committed
1870 1871 1872 1873 1874 1875
        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
1876
      
1877
      if (ru->wait_cnt > 0) {
Raymond Knopp's avatar
Raymond Knopp committed
1878
	
Raymond Knopp's avatar
Raymond Knopp committed
1879
        ru->wait_cnt--;
1880
        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
1881
	
Raymond Knopp's avatar
Raymond Knopp committed
1882
        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
1883
	  // Send RRU_frame adjust
Raymond Knopp's avatar
Raymond Knopp committed
1884 1885 1886 1887 1888
          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;
1889
          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
1890 1891 1892
          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;
        }
1893
        wakeup_L1s(ru);
Raymond Knopp's avatar
Raymond Knopp committed
1894
      }
Raymond Knopp's avatar
Raymond Knopp committed
1895
      else {
yilmazt's avatar
yilmazt committed
1896
        LOG_D(PHY,"RU thread %d, frame %d, subframe %d (do_prach %d, is_prach_subframe %d)\n",
1897 1898
              ru->idx, frame, subframe, ru->do_prach, is_prach_subframe(ru->frame_parms, proc->frame_rx, proc->tti_rx));
        if ((ru->do_prach>0) && (is_prach_subframe(ru->frame_parms, proc->frame_rx, proc->tti_rx)==1)) {
yilmazt's avatar
yilmazt committed
1899
          LOG_D(PHY,"Waking up prach for %d.%d\n", proc->frame_rx, proc->tti_rx);
Raymond Knopp's avatar
Raymond Knopp committed
1900
          wakeup_prach_ru(ru);
1901
        }
1902
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1903
        else if ((ru->do_prach>0) && (is_prach_subframe(ru->frame_parms, proc->frame_rx, proc->tti_rx)>1)) {
Raymond Knopp's avatar
Raymond Knopp committed
1904
          wakeup_prach_ru_br(ru);
yilmazt's avatar
yilmazt committed
1905
        }
1906
#endif
Raymond Knopp's avatar
Raymond Knopp committed
1907 1908 1909 1910 1911 1912 1913 1914
	
	// 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);
	
Raymond Knopp's avatar
Raymond Knopp committed
1915
    // do RX front-end processing (frequency-shift, dft) if needed
yilmazt's avatar
yilmazt committed
1916
	if (ru->feprx) ru->feprx(ru,proc->tti_rx);
Raymond Knopp's avatar
Raymond Knopp committed
1917
	
yilmazt's avatar
yilmazt committed
1918 1919
    // wakeup all eNB processes waiting for this RU
    AssertFatal((ret=pthread_mutex_lock(&proc->mutex_eNBs))==0,"mutex_lock returns %d\n",ret);
1920
	if (proc->instance_cnt_eNBs==0) proc->instance_cnt_eNBs--;
yilmazt's avatar
yilmazt committed
1921
      AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_eNBs))==0,"mutex_unlock returns %d\n",ret);
Raymond Knopp's avatar
Raymond Knopp committed
1922

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1923
#if defined(PRE_SCD_THREAD)
1924 1925 1926 1927
	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
1928
        AssertFatal((ret=pthread_mutex_lock(&ru->proc.mutex_pre_scd))==0,"[eNB] error locking proc mutex for eNB pre scd\n");
1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940
	
	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
1941

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1942
	AssertFatal((ret=pthread_mutex_unlock(&ru->proc.mutex_pre_scd))==0,"[eNB] error unlocking mutex_pre_scd mutex for eNB pre scd\n");
1943

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1944
#endif
Raymond Knopp's avatar
Raymond Knopp committed
1945 1946 1947
	// 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
1948
#ifndef PHY_TX_THREAD
1949
    if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD || ru->num_eNB==0) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1950
      // do TX front-end processing if needed (precoding and/or IDFTs)
yilmazt's avatar
yilmazt committed
1951
      if (ru->feptx_prec) ru->feptx_prec(ru, proc->frame_tx, proc->tti_tx);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1952 1953
      
      // do OFDM if needed
yilmazt's avatar
yilmazt committed
1954
      if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru, proc->frame_tx, proc->tti_tx);
1955
      if(!(get_softmodem_params()->emulate_rf)) { //if(!emulate_rf){
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1956
        // do outgoing fronthaul (south) if needed
1957
        if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,proc->frame_tx,proc->tti_tx,proc->timestamp_tx);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1958
        
yilmazt's avatar
yilmazt committed
1959
        if ((ru->fh_north_out) && (ru->state!=RU_CHECK_SYNC)) ru->fh_north_out(ru);
1960
      }
Florian Kaltenberger's avatar
Florian Kaltenberger committed
1961
      else {
yilmazt's avatar
yilmazt committed
1962 1963 1964
        for (int i=0; i<ru->nb_tx; i++) {
          if(proc->frame_tx == 2) {
            sprintf(filename,"txdataF%d_frame%d_sf%d.m",i,proc->frame_tx,proc->tti_tx);
1965
            LOG_M(filename,"txdataF_frame",ru->common.txdataF_BF[i],ru->frame_parms->symbols_per_tti*ru->frame_parms->ofdm_symbol_size, 1, 1);
yilmazt's avatar
yilmazt committed
1966 1967 1968
          }
          if(proc->frame_tx == 2 && proc->tti_tx==0){
            sprintf(filename,"txdata%d_frame%d.m",i,proc->frame_tx);
1969
            LOG_M(filename,"txdata_frame",ru->common.txdata[i],ru->frame_parms->samples_per_tti*10, 1, 1);
yilmazt's avatar
yilmazt committed
1970 1971
          }
        }
Florian Kaltenberger's avatar
Florian Kaltenberger committed
1972
      }
1973
      proc->emulate_rf_busy = 0;
1974
    }
1975

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1976
#else
1977 1978 1979 1980 1981 1982 1983 1984
	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
1985
#endif
1986
      } // else wait_cnt == 0
1987
    } // ru->state = RU_RUN
1988
  } // while !oai_exit
Raymond Knopp's avatar
Raymond Knopp committed
1989
  
Raymond Knopp's avatar
Raymond Knopp committed
1990
  printf( "Exiting ru_thread \n");
Raymond Knopp's avatar
Raymond Knopp committed
1991
  
1992
  if (!(get_softmodem_params()->emulate_rf)) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1993 1994 1995 1996 1997
    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);
    }
1998
  }
Raymond Knopp's avatar
Raymond Knopp committed
1999
  return NULL;
Raymond Knopp's avatar
Raymond Knopp committed
2000 2001 2002
}

// This thread run the initial synchronization like a UE
2003 2004
void *ru_thread_synch(void *arg)
{
2005
  RU_t *ru = (RU_t *)arg;
2006
  LTE_DL_FRAME_PARMS *fp = ru->frame_parms;
yilmazt's avatar
yilmazt committed
2007 2008
  int64_t peak_val, avg;
  static int ru_thread_synch_status = 0;
Eurecom's avatar
Eurecom committed
2009
  int cnt=0;
Raymond Knopp's avatar
Raymond Knopp committed
2010 2011 2012
  thread_top_init("ru_thread_synch",0,5000000,10000000,10000000);
  wait_sync("ru_thread_synch");
  // initialize variables for PSS detection
yilmazt's avatar
yilmazt committed
2013
  ru_sync_time_init(ru); //lte_sync_time_init(ru->frame_parms);
Raymond Knopp's avatar
Raymond Knopp committed
2014 2015 2016

  while (!oai_exit) {
    // wait to be woken up
2017
    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
2018 2019

    // if we're not in synch, then run initial synch
2020
    if (ru->in_synch == 0) {
Raymond Knopp's avatar
Raymond Knopp committed
2021 2022
      // run intial synch like UE
      LOG_I(PHY,"Running initial synchronization\n");
2023
      ru->rx_offset = ru_sync_time(ru,
Raymond Knopp's avatar
Raymond Knopp committed
2024
				   &peak_val,
2025
				   &avg);
2026
      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
2027
      cnt++;
2028 2029
      //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) {
yilmazt's avatar
yilmazt committed
2030 2031
        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);
        ru->in_synch = 1;
2032
/*
2033
        LOG_M("ru_sync_rx.m","rurx",&ru->common.rxdata[0][0],LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*fp->samples_per_tti,1,1);
2034 2035
        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);
2036 2037
  */      
//exit(-1);
2038
      } // sync_pos > 0
2039
      else //AssertFatal(cnt<1000,"Cannot find synch reference\n");
2040
          {
2041 2042
              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);
2043 2044 2045
                 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);

2046 2047
                 exit(-1);
              }
2048
          }
Eurecom's avatar
Eurecom committed
2049
    } // ru->in_synch==0
Raymond Knopp's avatar
Raymond Knopp committed
2050 2051 2052
    if (release_thread(&ru->proc.mutex_synch,&ru->proc.instance_cnt_synch,"ru_synch_thread") < 0) break;
  } // oai_exit

2053
  ru_sync_time_free(ru);
Raymond Knopp's avatar
Raymond Knopp committed
2054

2055 2056
  ru_thread_synch_status = 0;
  return &ru_thread_synch_status;
Raymond Knopp's avatar
Raymond Knopp committed
2057 2058
}

yilmazt's avatar
yilmazt committed
2059

Wang Tsu-Han's avatar
Wang Tsu-Han committed
2060
#if defined(PRE_SCD_THREAD)
2061 2062
void *pre_scd_thread( void *param )
{
2063 2064 2065 2066 2067 2068 2069 2070
  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
2071
  int                     ret;
2072 2073

  // L2-emulator can work only one eNB
frtabu's avatar
frtabu committed
2074
  if( NFAPI_MODE==NFAPI_MODE_VNF)
2075 2076
    Mod_id = 0;
  else
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2077 2078
    Mod_id = ru->eNB_list[0]->Mod_id;

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

2083 2084 2085 2086
  while (!oai_exit) {
    if(oai_exit) {
      break;
    }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2087

Wang Tsu-Han's avatar
Wang Tsu-Han committed
2088
    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
2089

2090 2091 2092
    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
2093

Wang Tsu-Han's avatar
Wang Tsu-Han committed
2094
    AssertFatal((ret=pthread_mutex_unlock(&ru->proc.mutex_pre_scd))==0,"mutex_unlock returns %d\n",ret);
2095 2096 2097
    PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, Mod_id, ENB_FLAG_YES,
                                   NOT_A_RNTI, frame, subframe,Mod_id);
    pdcp_run(&ctxt);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2098

2099 2100 2101
    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
2102
    }
2103 2104 2105 2106 2107 2108 2109 2110 2111

    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
2112
    }
2113

Wang Tsu-Han's avatar
Wang Tsu-Han committed
2114
    AssertFatal((ret=pthread_mutex_lock(&ru->proc.mutex_pre_scd ))==0,"mutex_lock returns %d\n",ret);
2115
    ru->proc.instance_pre_scd--;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2116
    AssertFatal((ret=pthread_mutex_unlock(&ru->proc.mutex_pre_scd))==0,"mutex_unlock returns %d\n",ret);
2117 2118 2119 2120
  }

  eNB_pre_scd_status = 0;
  return &eNB_pre_scd_status;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2121 2122 2123
}
#endif

yilmazt's avatar
yilmazt committed
2124

Wang Tsu-Han's avatar
Wang Tsu-Han committed
2125 2126 2127
#ifdef PHY_TX_THREAD
/*!
 * \brief The phy tx thread of eNB.
2128
 * \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
2129 2130
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
2131 2132
static void *eNB_thread_phy_tx( void *param )
{
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2133
  static int eNB_thread_phy_tx_status;
yilmazt's avatar
yilmazt committed
2134
  RU_t *ru        = (RU_t *)param;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2135 2136
  RU_proc_t *proc = &ru->proc;
  PHY_VARS_eNB **eNB_list = ru->eNB_list;
2137
  L1_rxtx_proc_t L1_proc;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2138 2139
  // set default return value
  eNB_thread_phy_tx_status = 0;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2140
  int ret;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2141 2142 2143 2144 2145 2146 2147 2148
  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");
yilmazt's avatar
yilmazt committed
2149
    AssertFatal(ru->num_eNB == 1, "Handle multiple L1 case\n");
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2150
    if(ru->num_eNB == 1){
2151 2152 2153
       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);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2154
       phy_tx_txdataF_end = 1;
2155

Wang Tsu-Han's avatar
Wang Tsu-Han committed
2156 2157 2158 2159
       if(pthread_mutex_lock(&ru->proc.mutex_rf_tx) != 0){
          LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for rf tx thread (IC %d)\n", ru->proc.instance_cnt_rf_tx);
          exit_fun( "error locking mutex_rf_tx" );
        }
2160

2161
       if (ru->proc.instance_cnt_rf_tx==-1) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2162 2163
          ++ru->proc.instance_cnt_rf_tx;
          ru->proc.frame_tx = proc->frame_phy_tx;
2164
          ru->proc.tti_tx = proc->subframe_phy_tx;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2165 2166 2167 2168 2169 2170 2171 2172 2173 2174
          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;
        }
        pthread_mutex_unlock( &ru->proc.mutex_rf_tx );
    }
2175

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

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

Wang Tsu-Han's avatar
Wang Tsu-Han committed
2180 2181 2182 2183 2184 2185 2186 2187 2188
    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;
}


yilmazt's avatar
yilmazt committed
2189 2190
static void *rf_tx( void *param )
{
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2191
  static int rf_tx_status;
2192
  RU_t *ru      = (RU_t *)param;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2193 2194 2195 2196 2197
  RU_proc_t *proc = &ru->proc;
  // set default return value
  rf_tx_status = 0;
  thread_top_init("rf_tx",1,500000L,1000000L,20000000L);

2198
  while (!oai_exit) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2199 2200 2201 2202 2203 2204
    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");

2205 2206 2207 2208 2209
    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
2210
      if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,proc->frame_tx,proc->tti_tx);
2211 2212 2213

      if(!emulate_rf) {
        // do outgoing fronthaul (south) if needed
2214
        if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,proc->frame_tx,proc->tti_tx,proc->timestamp_tx);
2215 2216 2217

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

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

    if(proc->instance_cnt_rf_tx >= 0) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233
      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
2234

2235 2236 2237 2238 2239 2240 2241 2242
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));
}

2243
int stop_rf(RU_t *ru) {
2244 2245 2246 2247
  ru->rfdevice.trx_end_func(&ru->rfdevice);
  return 0;
}

yilmazt's avatar
yilmazt committed
2248 2249

extern void configure_ru(int idx, void *arg);
2250
extern void fep_full(RU_t *ru,int subframe);
2251 2252 2253
extern void feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx);
extern void feptx_ofdm_2thread(RU_t *ru,int frame_tx,int tti_tx);
extern void feptx_prec(RU_t *ru,int frame_tx,int tti_tx);
2254 2255
extern void init_fep_thread(RU_t *ru, pthread_attr_t *attr_fep);
extern void init_feptx_thread(RU_t *ru, pthread_attr_t *attr_feptx);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2256 2257
extern void kill_fep_thread(RU_t *ru);
extern void kill_feptx_thread(RU_t *ru);
yilmazt's avatar
yilmazt committed
2258
extern void ru_fep_full_2thread(RU_t *ru,int subframe);
2259

2260

yilmazt's avatar
yilmazt committed
2261 2262
void reset_proc(RU_t *ru)
{
2263 2264
  int i=0;
  RU_proc_t *proc;
2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277

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

yilmazt's avatar
yilmazt committed
2278

2279 2280
extern void* ru_thread_control( void* param );

yilmazt's avatar
yilmazt committed
2281 2282 2283

void init_RU_proc(RU_t *ru)
{
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2284
  int i=0,ret;
2285
  RU_proc_t *proc;
yilmazt's avatar
yilmazt committed
2286
  pthread_attr_t *attr_FH=NULL, *attr_FH1=NULL, *attr_prach=NULL, *attr_asynch=NULL, *attr_synch=NULL, *attr_emulateRF=NULL, *attr_ctrl=NULL;
2287
  //pthread_attr_t *attr_fep=NULL;
2288
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
2289 2290
  pthread_attr_t *attr_prach_br=NULL;
#endif
2291 2292

#ifndef OCP_FRAMEWORK
Guy De Souza's avatar
Guy De Souza committed
2293
  LOG_I(PHY,"Initializing RU proc %d (%s,%s),\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing]);
2294 2295
#endif
  proc = &ru->proc;
2296
  memset((void *)proc,0,sizeof(RU_proc_t));
2297 2298
  proc->ru = ru;
  proc->instance_cnt_prach       = -1;
2299
  proc->instance_cnt_synch       = -1;
2300
  proc->instance_cnt_FH          = -1;
2301
  proc->instance_cnt_FH1         = -1;
2302
  proc->instance_cnt_emulateRF   = -1;
2303
  proc->instance_cnt_asynch_rxtx = -1;
yilmazt's avatar
yilmazt committed
2304
  proc->instance_cnt_ru          = -1;
2305
  proc->instance_cnt_eNBs        = -1;
2306 2307 2308 2309
  proc->first_rx                 = 1;
  proc->first_tx                 = 1;
  proc->frame_offset             = 0;
  proc->num_slaves               = 0;
2310 2311
  proc->frame_tx_unwrap          = 0;

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

2314 2315 2316 2317
  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);
2318
  pthread_mutex_init( &proc->mutex_FH1,NULL);
2319
  pthread_mutex_init( &proc->mutex_emulateRF,NULL);
2320
  pthread_mutex_init( &proc->mutex_eNBs, NULL);
2321
  pthread_mutex_init( &proc->mutex_ru,NULL);
2322

2323 2324
  pthread_cond_init( &proc->cond_prach, NULL);
  pthread_cond_init( &proc->cond_FH, NULL);
2325
  pthread_cond_init( &proc->cond_FH1, NULL);
2326
  pthread_cond_init( &proc->cond_emulateRF, NULL);
2327 2328
  pthread_cond_init( &proc->cond_asynch_rxtx, NULL);
  pthread_cond_init( &proc->cond_synch,NULL);
2329
  pthread_cond_init( &proc->cond_eNBs, NULL);
2330
  pthread_cond_init( &proc->cond_ru_thread,NULL);
2331

2332
  pthread_attr_init( &proc->attr_FH);
2333
  pthread_attr_init( &proc->attr_FH1);
2334
  pthread_attr_init( &proc->attr_emulateRF);
2335 2336 2337 2338
  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);
2339
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
yilmazt's avatar
yilmazt committed
2340
  proc->instance_cnt_prach_br = -1;
2341 2342 2343
  pthread_mutex_init( &proc->mutex_prach_br, NULL);
  pthread_cond_init( &proc->cond_prach_br, NULL);
  pthread_attr_init( &proc->attr_prach_br);
2344
#endif
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2345
#ifdef PHY_TX_THREAD
yilmazt's avatar
yilmazt committed
2346
  proc->instance_cnt_phy_tx = -1;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2347 2348
  pthread_mutex_init( &proc->mutex_phy_tx, NULL);
  pthread_cond_init( &proc->cond_phy_tx, NULL);
yilmazt's avatar
yilmazt committed
2349
  proc->instance_cnt_rf_tx = -1;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2350 2351 2352
  pthread_mutex_init( &proc->mutex_rf_tx, NULL);
  pthread_cond_init( &proc->cond_rf_tx, NULL);
#endif
2353
#ifndef DEADLINE_SCHEDULER
2354
  attr_FH        = &proc->attr_FH;
2355
  attr_FH1       = &proc->attr_FH1;
2356 2357 2358
  attr_prach     = &proc->attr_prach;
  attr_synch     = &proc->attr_synch;
  attr_asynch    = &proc->attr_asynch_rxtx;
2359
  attr_emulateRF = &proc->attr_emulateRF;
2360
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
2361 2362
  attr_prach_br  = &proc->attr_prach_br;
#endif
2363
#endif
2364
  if (ru->function!=eNodeB_3GPP) pthread_create( &proc->pthread_ctrl, attr_ctrl, ru_thread_control, (void*)ru );
Raymond Knopp's avatar
Raymond Knopp committed
2365

2366
  pthread_create( &proc->pthread_FH, attr_FH, ru_thread, (void*)ru );
2367

Wang Tsu-Han's avatar
Wang Tsu-Han committed
2368
#if defined(PRE_SCD_THREAD)
2369 2370 2371 2372 2373
  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
2374 2375
#endif
#ifdef PHY_TX_THREAD
2376 2377 2378
  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
2379 2380
#endif

yilmazt's avatar
yilmazt committed
2381
  if (get_softmodem_params()->emulate_rf)
2382
    pthread_create( &proc->pthread_emulateRF, attr_emulateRF, emulatedRF_thread, (void *)proc );
2383

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

2387
  if (ru->function == NGFI_RRU_IF4p5) {
2388 2389 2390
    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 );
2391
#endif
2392 2393 2394

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

yilmazt's avatar
yilmazt committed
2395
    if ((ru->if_timing == synch_to_other) || (ru->function == NGFI_RRU_IF5) || (ru->function == NGFI_RRU_IF4p5)) {
2396 2397
        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
2398 2399 2400
	//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 );
2401
    }
Raymond Knopp's avatar
Raymond Knopp committed
2402
  }
2403
  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
2404
    LOG_I(PHY,"%s() DJP - added creation of pthread_prach\n", __FUNCTION__);
2405
    pthread_create( &proc->pthread_prach, attr_prach, ru_thread_prach, (void*)ru );
2406 2407
    ru->state=RU_RUN;
    fill_rf_config(ru,ru->rf_config_file);
2408
    init_frame_parms(ru->frame_parms,1);
yilmazt's avatar
yilmazt committed
2409
    ru->frame_parms->nb_antennas_rx = ru->nb_rx;
2410 2411 2412 2413
    phy_init_RU(ru);

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

yilmazt's avatar
yilmazt committed
2414
    if (setup_RU_buffers(ru)!=0) {
2415 2416
      printf("Exiting, cannot initialize RU Buffers\n");
      exit(-1);
yilmazt's avatar
yilmazt committed
2417
    }
2418
  }
2419

2420
  if (get_thread_worker_conf() == WORKER_ENABLE) {
2421 2422
    init_fep_thread(ru, NULL);
    init_feptx_thread(ru, NULL);
2423
  } 
2424
  if (opp_enabled == 1) pthread_create(&ru->ru_stats_thread,NULL,ru_stats_thread,(void*)ru); 
2425 2426 2427
 
  if (ru->function == eNodeB_3GPP) {
    usleep(10000);
2428
    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
2429
    AssertFatal((ret=pthread_mutex_lock(&RC.ru_mutex))==0,"mutex_lock returns %d\n",ret);
2430 2431
    RC.ru_mask &= ~(1<<ru->idx);
    pthread_cond_signal(&RC.ru_cond);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2432
    AssertFatal((ret=pthread_mutex_unlock(&RC.ru_mutex))==0,"mutex_unlock returns %d\n",ret);
2433
  }
2434 2435
}

yilmazt's avatar
yilmazt committed
2436 2437 2438

void kill_RU_proc(RU_t *ru)
{
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2439
  int ret;
Robert Schmidt's avatar
Robert Schmidt committed
2440
  RU_proc_t *proc = &ru->proc;
Robert Schmidt's avatar
Robert Schmidt committed
2441
#if defined(PRE_SCD_THREAD)
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2442
  AssertFatal((ret=pthread_mutex_lock(&proc->mutex_pre_scd))==0,"mutex_lock returns %d\n",ret);
Robert Schmidt's avatar
Robert Schmidt committed
2443 2444
  ru->proc.instance_pre_scd = 0;
  pthread_cond_signal(&proc->cond_pre_scd);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2445
  AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_pre_scd))==0,"mutex_unlock returns %d\n",ret);
Robert Schmidt's avatar
Robert Schmidt committed
2446 2447 2448 2449 2450
  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
2451
  AssertFatal((ret=pthread_mutex_lock(&proc->mutex_phy_tx))==0,"mutex_lock returns %d\n",ret);
Robert Schmidt's avatar
Robert Schmidt committed
2452 2453
  proc->instance_cnt_phy_tx = 0;
  pthread_cond_signal(&proc->cond_phy_tx);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2454
  AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_phy_tx))==0,"mutex_unlock returns %d\n",ret);
Robert Schmidt's avatar
Robert Schmidt committed
2455 2456 2457
  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
2458
  AssertFatal((ret=pthread_mutex_lock(&proc->mutex_rf_tx))==0,"mutex_lock returns %d\n",ret);
Robert Schmidt's avatar
Robert Schmidt committed
2459 2460
  proc->instance_cnt_rf_tx = 0;
  pthread_cond_signal(&proc->cond_rf_tx);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2461
  AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_rf_tx))==0,"mutex_unlock returns %d\n",ret);
Robert Schmidt's avatar
Robert Schmidt committed
2462 2463 2464 2465 2466
  pthread_join(proc->pthread_rf_tx, NULL);
  pthread_mutex_destroy( &proc->mutex_rf_tx);
  pthread_cond_destroy( &proc->cond_rf_tx);
#endif

2467
  if (get_thread_worker_conf() == WORKER_ENABLE) {
2468 2469 2470 2471
    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
2472 2473
  }

Wang Tsu-Han's avatar
Wang Tsu-Han committed
2474
  AssertFatal((ret=pthread_mutex_lock(&proc->mutex_FH))==0,"mutex_lock returns %d\n",ret);
Robert Schmidt's avatar
Robert Schmidt committed
2475 2476
  proc->instance_cnt_FH = 0;
  pthread_cond_signal(&proc->cond_FH);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2477 2478
  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
2479 2480
  proc->instance_cnt_FH1 = 0;
  pthread_cond_signal(&proc->cond_FH1);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2481 2482
  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
2483 2484
  proc->instance_cnt_prach = 0;
  pthread_cond_signal(&proc->cond_prach);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2485
  AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_prach))==0,"mutex_unlock returns %d\n",ret);
2486
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2487
  AssertFatal((ret=pthread_mutex_lock(&proc->mutex_prach_br))==0,"mutex_lock returns %d\n",ret);
Robert Schmidt's avatar
Robert Schmidt committed
2488 2489
  proc->instance_cnt_prach_br = 0;
  pthread_cond_signal(&proc->cond_prach_br);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2490
  AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_prach_br))==0,"mutex_unlock returns %d\n",ret);
Robert Schmidt's avatar
Robert Schmidt committed
2491
#endif
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2492
  AssertFatal((ret=pthread_mutex_lock(&proc->mutex_synch))==0,"mutex_lock returns %d\n",ret);
Robert Schmidt's avatar
Robert Schmidt committed
2493 2494
  proc->instance_cnt_synch = 0;
  pthread_cond_signal(&proc->cond_synch);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2495 2496
  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
2497 2498 2499 2500
  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
2501 2502
  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
2503 2504
  proc->instance_cnt_asynch_rxtx = 0;
  pthread_cond_signal(&proc->cond_asynch_rxtx);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2505
  AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_asynch_rxtx))==0,"mutex_unlock returns %d\n",ret);
Robert Schmidt's avatar
Robert Schmidt committed
2506
  LOG_D(PHY, "Joining pthread_FH\n");
Robert Schmidt's avatar
Robert Schmidt committed
2507
  pthread_join(proc->pthread_FH, NULL);
2508

2509
  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
2510 2511 2512
    LOG_D(PHY, "Joining pthread_FHTX\n");
    pthread_join(proc->pthread_FH1, NULL);
  }
2513

Robert Schmidt's avatar
Robert Schmidt committed
2514 2515 2516
  if (ru->function == NGFI_RRU_IF4p5) {
    LOG_D(PHY, "Joining pthread_prach\n");
    pthread_join(proc->pthread_prach, NULL);
2517
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
Robert Schmidt's avatar
Robert Schmidt committed
2518 2519 2520
    LOG_D(PHY, "Joining pthread_prach_br\n");
    pthread_join(proc->pthread_prach_br, NULL);
#endif
2521

Robert Schmidt's avatar
Robert Schmidt committed
2522 2523 2524 2525
    if (ru->is_slave) {
      LOG_D(PHY, "Joining pthread_\n");
      pthread_join(proc->pthread_synch, NULL);
    }
2526

Robert Schmidt's avatar
Robert Schmidt committed
2527 2528 2529 2530 2531 2532 2533
    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);
    }
  }
2534

Robert Schmidt's avatar
Robert Schmidt committed
2535 2536 2537 2538 2539 2540 2541 2542 2543
  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);
2544
  pthread_mutex_destroy(&proc->mutex_FH1);
Robert Schmidt's avatar
Robert Schmidt committed
2545 2546 2547
  pthread_mutex_destroy(&proc->mutex_eNBs);
  pthread_cond_destroy(&proc->cond_prach);
  pthread_cond_destroy(&proc->cond_FH);
2548
  pthread_cond_destroy(&proc->cond_FH1);
Robert Schmidt's avatar
Robert Schmidt committed
2549 2550 2551 2552
  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);
2553
  pthread_attr_destroy(&proc->attr_FH1);
Robert Schmidt's avatar
Robert Schmidt committed
2554 2555 2556 2557
  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);
2558
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
Robert Schmidt's avatar
Robert Schmidt committed
2559 2560 2561 2562 2563
  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
2564

2565

2566 2567
void init_precoding_weights(PHY_VARS_eNB *eNB)
{
2568
  int layer,ru_id,aa,re,ue,tb;
2569
  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
2570 2571 2572 2573
  RU_t *ru;
  LTE_eNB_DLSCH_t *dlsch;

  // init precoding weigths
2574 2575
  for (ue=0; ue<NUMBER_OF_UE_MAX; ue++) {
    for (tb=0; tb<2; tb++) {
2576
      dlsch = eNB->dlsch[ue][tb];
2577

2578
      for (layer=0; layer<4; layer++) {
2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594
        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;
          }
        }
2595 2596 2597 2598 2599
      }
    }
  }
}

yilmazt's avatar
yilmazt committed
2600

2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625
void set_function_spec_param(RU_t *ru)
{
  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);
2626
      
2627 2628 2629 2630
      if (ret<0) {
        printf("Exiting, cannot initialize transport protocol\n");
        exit(-1);
      }
2631
    } else if (ru->function == NGFI_RRU_IF4p5) {
2632 2633 2634 2635 2636
      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
2637 2638
      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)
2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649
      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);
2650
      
2651 2652 2653 2654
      if (ret<0) {
        printf("Exiting, cannot initialize transport protocol\n");
        exit(-1);
      }
2655
      
2656
      malloc_IF4p5_buffer(ru);
2657
    } else if (ru->function == eNodeB_3GPP) {
2658
      ru->do_prach             = 0;                       // no prach processing in RU
2659 2660
      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
2661 2662 2663 2664 2665 2666
      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;
    }
2667
    
2668 2669 2670
    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
2671
    ru->stop_rf                = stop_rf;
2672
    printf("configuring ru_id %d (start_rf %p)\n", ru->idx, start_rf);
Raymond Knopp's avatar
Raymond Knopp committed
2673 2674
    /*
      if (ru->function == eNodeB_3GPP) { // configure RF parameters only for 3GPP eNodeB, we need to get them from RAU otherwise
2675 2676 2677
      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
2678
      }
2679
      
Raymond Knopp's avatar
Raymond Knopp committed
2680 2681
      ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg);
      if (setup_RU_buffers(ru)!=0) {
2682 2683
      printf("Exiting, cannot initialize RU Buffers\n");
      exit(-1);
Raymond Knopp's avatar
Raymond Knopp committed
2684
      }*/
2685
    break;
2686
    
2687 2688
  case REMOTE_IF5: // the remote unit is IF5 RRU
    ru->do_prach               = 0;
2689
    ru->feprx                  = (get_thread_worker_conf() == WORKER_DISABLE) ? fep_full : fep_full;                   // this is frequency-shift + DFTs
2690
    ru->feptx_prec             = feptx_prec;                 // need to do transmit Precoding + IDFTs
2691
    ru->feptx_ofdm             = (get_thread_worker_conf() == WORKER_DISABLE) ? feptx_ofdm : feptx_ofdm_2thread;                 // need to do transmit Precoding + IDFTs
2692 2693 2694
    
    if (ru->if_timing == synch_to_other) {
      ru->fh_south_in          = fh_slave_south_in;                  // synchronize to master
yilmazt's avatar
yilmazt committed
2695 2696
      ru->fh_south_out         = fh_if5_mobipass_south_out;          // use send_IF5 for mobipass
      ru->fh_south_asynch_in   = fh_if5_south_asynch_in_mobipass;    // UL is asynchronous
2697 2698 2699 2700 2701 2702
    } 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
    }
    
2703
    ru->start_rf               = NULL;                 // no local RF
2704
    ru->stop_rf                = NULL;
2705 2706 2707 2708 2709 2710
    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);
2711
    
2712 2713 2714 2715
    if (ret<0) {
      printf("Exiting, cannot initialize transport protocol\n");
      exit(-1);
    }
2716
    
2717
    break;
2718
    
2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729
  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
2730
    ru->stop_rf                = NULL;
2731 2732 2733 2734 2735 2736
    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);
2737
    
2738 2739 2740 2741 2742 2743
    if (ret<0) {
      printf("Exiting, cannot initialize transport protocol\n");
      exit(-1);
    }
    malloc_IF4p5_buffer(ru);
    break;
2744
  
2745 2746 2747 2748 2749
  default:
    LOG_E(PHY,"RU with invalid or unknown southbound interface type %d\n",ru->if_south);
    break;
  } // switch on interface type
}
2750
 
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2751
//extern void RCconfig_RU(void);
Raymond Knopp's avatar
Raymond Knopp committed
2752

yilmazt's avatar
yilmazt committed
2753 2754 2755 2756
void init_RU(char *rf_config_file,
             clock_source_t clock_source,
             clock_source_t time_source,
             int send_dmrssync)
2757
{
Raymond Knopp's avatar
Raymond Knopp committed
2758
  int ru_id;
2759
  RU_t *ru;
2760
  PHY_VARS_eNB *eNB0     = (PHY_VARS_eNB *)NULL;
2761
  LTE_DL_FRAME_PARMS *fp = (LTE_DL_FRAME_PARMS *)NULL;
2762 2763 2764 2765 2766 2767
  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);
2768 2769
  // read in configuration file)
  printf("configuring RU from file\n");
2770
  RCconfig_RU();
2771
  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());
2772

2773
  if (RC.nb_CC != 0)
2774 2775
    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;
2776

Cedric Roux's avatar
Cedric Roux committed
2777
  LOG_D(PHY,"Process RUs RC.nb_RU:%d\n",RC.nb_RU);
2778 2779

  for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
Cedric Roux's avatar
Cedric Roux committed
2780
    LOG_D(PHY,"Process RC.ru[%d]\n",ru_id);
2781
    ru               = RC.ru[ru_id];
2782
    ru->rf_config_file = rf_config_file;
2783
    ru->idx          = ru_id;
2784
    ru->ts_offset    = 0;
2785 2786
    if (ru->is_slave == 1) {
       ru->in_synch    = 0;
Raymond Knopp's avatar
Raymond Knopp committed
2787
       ru->generate_dmrs_sync = 0; 	
2788 2789 2790 2791 2792
    }
    else {
       ru->in_synch    = 1;
       ru->generate_dmrs_sync=send_dmrssync;
    }
2793
    ru->cmd	     = EMPTY;
2794
    ru->south_out_cnt= 0;
2795 2796
    // use eNB_list[0] as a reference for RU frame parameters
    // NOTE: multiple CC_id are not handled here yet!
2797 2798
    ru->openair0_cfg.clock_source  = clock_source;
    ru->openair0_cfg.time_source = time_source;
2799 2800 2801 2802 2803
    //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
2804
    if (ru->generate_dmrs_sync == 1) {
Raymond Knopp's avatar
Raymond Knopp committed
2805
      generate_ul_ref_sigs();
2806
      ru->dmrssync = (int16_t*)malloc16_clear(ru->frame_parms->ofdm_symbol_size*2*sizeof(int16_t));
magounak's avatar
magounak committed
2807
    }
2808 2809
    ru->wakeup_L1_sleeptime = 2000;
    ru->wakeup_L1_sleep_cnt_max  = 3;
2810 2811
    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);
2812

2813
      if (ru->eNB_list[0] == 0) {
2814 2815 2816
        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;
2817 2818 2819 2820
        //
        // DJP - feptx_prec() / feptx_ofdm() parses the eNB_list (based on num_eNB) and copies the txdata_F to txdata in RU
        //
      } else {
2821 2822
        LOG_E(PHY,"DJP - delete code above this %s:%d\n", __FILE__, __LINE__);
      }
2823
    }
2824

2825
    eNB0             = ru->eNB_list[0];
2826
    fp               = ru->frame_parms;
Cedric Roux's avatar
Cedric Roux committed
2827
    LOG_D(PHY, "RU FUnction:%d ru->if_south:%d\n", ru->function, ru->if_south);
2828
    LOG_D(PHY, "eNB0:%p   fp:%p\n", eNB0, fp);
2829
    if (eNB0) {
2830 2831 2832 2833 2834
      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);
Cedric Roux's avatar
Cedric Roux committed
2835
        ru->frame_parms = &eNB0->frame_parms;
2836
        // attach all RU to all eNBs in its list/
Cedric Roux's avatar
Cedric Roux committed
2837
        LOG_D(PHY,"ru->num_eNB:%d eNB0->num_RU:%d\n", ru->num_eNB, eNB0->num_RU);
2838 2839

        for (i=0; i<ru->num_eNB; i++) {
2840 2841 2842
          eNB0 = ru->eNB_list[i];
          eNB0->RU_list[eNB0->num_RU++] = ru;
        }
2843
      }
2844
    }
2845
    LOG_I(PHY,"Initializing RRU descriptor %d : (%s,%s,%d)\n",ru_id,ru_if_types[ru->if_south],NB_timing[ru->if_timing],ru->function);
2846
    set_function_spec_param(ru);
2847
    LOG_I(PHY,"Starting ru_thread %d, is_slave %d, send_dmrs %d\n",ru_id,ru->is_slave,ru->generate_dmrs_sync);
2848 2849

    init_RU_proc(ru);
Raymond Knopp's avatar
Raymond Knopp committed
2850
  } // for ru_id
2851
  
2852
  //  sleep(1);
2853
  LOG_D(HW,"[lte-softmodem.c] RU threads created\n");
Raymond Knopp's avatar
Raymond Knopp committed
2854 2855
}

Wang Tsu-Han's avatar
Wang Tsu-Han committed
2856

yilmazt's avatar
yilmazt committed
2857 2858
void stop_ru(RU_t *ru)
{
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887
#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
}

yilmazt's avatar
yilmazt committed
2888

Robert Schmidt's avatar
Robert Schmidt committed
2889 2890 2891 2892
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
2893
    kill_RU_proc(RC.ru[inst]);
Robert Schmidt's avatar
Robert Schmidt committed
2894
  }
Raymond Knopp's avatar
Raymond Knopp committed
2895
}
2896

2897 2898 2899 2900 2901 2902 2903
//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;
2904
  //  PHY_VARS_eNB *eNB0= (PHY_VARS_eNB *)NULL;
2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917
  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)
2918 2919
    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;
2920 2921

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

  for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
2924 2925
    LOG_D(PHY,"Process RC.ru[%d]\n",ru_id);
    ru               = RC.ru[ru_id];
2926 2927
    //    ru->rf_config_file = rf_config_file;
    ru->idx          = ru_id;
2928 2929 2930 2931 2932
    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) {
2933 2934
      //      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) {
2935 2936 2937
        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;
2938 2939 2940 2941
        //
        // DJP - feptx_prec() / feptx_ofdm() parses the eNB_list (based on num_eNB) and copies the txdata_F to txdata in RU
        //
      } else {
2942 2943 2944 2945
        LOG_E(PHY,"DJP - delete code above this %s:%d\n", __FILE__, __LINE__);
      }
    }

2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966
    // 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;
            }
          }
2967
        }
2968
    */
2969
    LOG_I(PHY,"Initializing RRU descriptor %d : (%s,%s,%d)\n",ru_id,ru_if_types[ru->if_south],NB_timing[ru->if_timing],ru->function);
2970
    //    set_function_spec_param(ru);
2971
    LOG_I(PHY,"Starting ru_thread %d\n",ru_id);
2972
    //    init_RU_proc(ru);
2973
    proc = &ru->proc;
2974
    memset((void *)proc,0,sizeof(RU_proc_t));
2975 2976 2977
    proc->instance_pre_scd = -1;
    pthread_mutex_init( &proc->mutex_pre_scd, NULL);
    pthread_cond_init( &proc->cond_pre_scd, NULL);
2978
    pthread_create(&proc->pthread_pre_scd, NULL, pre_scd_thread, (void *)ru);
2979 2980 2981 2982 2983 2984 2985 2986
    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
2987

2988 2989
/* --------------------------------------------------------*/
/* from here function to use configuration module          */
2990 2991
void RCconfig_RU(void)
{
2992
  int i = 0;
2993 2994
  paramdef_t RUParams[] = RUPARAMS_DESC;
  paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0};
2995
  config_getlist( &RUParamList,RUParams,sizeof(RUParams)/sizeof(paramdef_t), NULL);
2996 2997

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

3002
    for (int j = 0; j < RC.nb_RU; j++) {
3003 3004
      RC.ru[j]                                    = (RU_t *)malloc(sizeof(RU_t));
      memset((void *)RC.ru[j],0,sizeof(RU_t));
3005 3006 3007
      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;
3008

3009 3010 3011
      if (RC.nb_L1_inst >0)
        RC.ru[j]->num_eNB                           = RUParamList.paramarray[j][RU_ENB_LIST_IDX].numelt;
      else
3012
        RC.ru[j]->num_eNB                           = 0;
3013
      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];     
3014

3015
      RC.ru[j]->has_ctrl_prt                        = 1;
3016

3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034
      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));
        }
      }
3035 3036

      if (strcmp(*(RUParamList.paramarray[j][RU_LOCAL_RF_IDX].strptr), "yes") == 0) {
3037 3038 3039
        if ( !(config_isparamset(RUParamList.paramarray[j],RU_LOCAL_IF_NAME_IDX)) ) {
          RC.ru[j]->if_south                        = LOCAL_RF;
          RC.ru[j]->function                        = eNodeB_3GPP;
3040
          RC.ru[j]->state                           = RU_RUN;
3041
          printf("Setting function for RU %d to eNodeB_3GPP\n",j);
3042 3043 3044 3045 3046 3047 3048 3049
        }
        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);

3050 3051
	  // Check if control port set
	  if  (!(config_isparamset(RUParamList.paramarray[j],RU_REMOTE_PORTC_IDX)) ){
yilmazt's avatar
yilmazt committed
3052
        printf("Removing control port for RU %d\n",j);
3053

yilmazt's avatar
yilmazt committed
3054 3055
        RC.ru[j]->has_ctrl_prt			      = 0;
      }
3056 3057 3058
	  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);
3059

3060 3061
	    printf(" Control port %u \n",RC.ru[j]->eth_params.my_portc);
	  }
3062

3063 3064 3065 3066
	  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;
3067
           
3068 3069 3070 3071 3072
	    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;
3073
	  
3074 3075 3076 3077 3078
	    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;
3079
	 
3080 3081 3082 3083 3084
	    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;
3085
	
3086 3087
	    printf("Setting function for RU %d to NGFI_RRU_IF4p5 (raw)\n",j);
	  }
3088
          printf("RU %d is_slave=%s\n",j,*(RUParamList.paramarray[j][RU_IS_SLAVE_IDX].strptr));
3089 3090
          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;
3091 3092 3093
          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;
3094 3095 3096 3097
	}
	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;
3098 3099
	/* 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);
3100 3101 3102
	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 {
3103
        printf("RU %d: Transport %s\n",j,*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr));
3104 3105
        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));
3106
        RC.ru[j]->eth_params.remote_addr        = strdup(*(RUParamList.paramarray[j][RU_REMOTE_ADDRESS_IDX].strptr));
3107
        RC.ru[j]->eth_params.my_portc           = *(RUParamList.paramarray[j][RU_LOCAL_PORTC_IDX].uptr);
3108
        RC.ru[j]->eth_params.remote_portc       = *(RUParamList.paramarray[j][RU_REMOTE_PORTC_IDX].uptr);
3109
        RC.ru[j]->eth_params.my_portd           = *(RUParamList.paramarray[j][RU_LOCAL_PORTD_IDX].uptr);
3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133
        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;
        } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw_if5_mobipass") == 0) {
          RC.ru[j]->if_south                     = REMOTE_IF5;
          RC.ru[j]->function                     = NGFI_RAU_IF5;
          RC.ru[j]->if_timing                    = synch_to_other;
          RC.ru[j]->eth_params.transp_preference = ETH_RAW_IF5_MOBIPASS;
        }
3134 3135
        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;
3136 3137 3138 3139
      }  /* 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);
3140 3141
      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);
3142 3143
    }// j=0..num_rus
  } else {
3144
    RC.nb_RU = 0;
3145 3146 3147 3148
  } // setting != NULL

  return;
}