nr-ru.c 83.7 KB
Newer Older
Raphael Defosseux's avatar
Raphael Defosseux committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
 * 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
Thomas Laurent's avatar
Thomas Laurent committed
20
 */
Raphael Defosseux's avatar
Raphael Defosseux committed
21

Thomas Laurent's avatar
Thomas Laurent committed
22
23
24
25
26
27
28
29
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sched.h>
#include <linux/sched.h>
#include <sys/sysinfo.h>
30
#include <math.h>
Thomas Laurent's avatar
Thomas Laurent committed
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all

#include "common/utils/assertions.h"
#include "common/utils/system.h"

#include "../../ARCH/COMMON/common_lib.h"
#include "../../ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h"

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

#include "PHY/types.h"
#include "PHY/defs_nr_common.h"
#include "PHY/phy_extern.h"
Guido Casati's avatar
Guido Casati committed
46
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
Thomas Laurent's avatar
Thomas Laurent committed
47
48
49
#include "PHY/INIT/phy_init.h"
#include "SCHED_NR/sched_nr.h"

50
#include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h"
Thomas Laurent's avatar
Thomas Laurent committed
51
52
53
54

#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"

frtabu's avatar
frtabu committed
55
#include <executables/softmodem-common.h>
Thomas Laurent's avatar
Thomas Laurent committed
56
57
58
59
60
61

#ifdef SMBV
#include "PHY/TOOLS/smbv.h"
unsigned short config_frames[4] = {2,9,11,13};
#endif

62
/* these variables have to be defined before including ENB_APP/enb_paramdef.h and GNB_APP/gnb_paramdef.h */
Thomas Laurent's avatar
Thomas Laurent committed
63
64
static int DEFBANDS[] = {7};
static int DEFENBS[] = {0};
65
static int DEFBFW[] = {0x00007fff};
Thomas Laurent's avatar
Thomas Laurent committed
66

67
68
//static int DEFNRBANDS[] = {7};
//static int DEFGNBS[] = {0};
69

Thomas Laurent's avatar
Thomas Laurent committed
70
#include "ENB_APP/enb_paramdef.h"
71
#include "GNB_APP/gnb_paramdef.h"
Thomas Laurent's avatar
Thomas Laurent committed
72
73
74
75
76
77
#include "common/config/config_userapi.h"

#ifndef OPENAIR2
  #include "UTIL/OTG/otg_extern.h"
#endif

78
79
#include "s1ap_eNB.h"
#include "SIMULATION/ETH_TRANSPORT/proto.h"
80
#include <openair1/PHY/TOOLS/phy_scope_interface.h>
81

Thomas Laurent's avatar
Thomas Laurent committed
82
83
84
85

#include "T.h"
#include "nfapi_interface.h"

86
extern volatile int oai_exit;
Thomas Laurent's avatar
Thomas Laurent committed
87
88
89
90


extern void  nr_phy_free_RU(RU_t *);
extern void  nr_phy_config_request(NR_PHY_Config_t *gNB);
91
92
93
#include "executables/thread-common.h"
//extern PARALLEL_CONF_t get_thread_parallel_conf(void);
//extern WORKER_CONF_t   get_thread_worker_conf(void);
Thomas Laurent's avatar
Thomas Laurent committed
94

95
void init_NR_RU(char *);
Thomas Laurent's avatar
Thomas Laurent committed
96
97
98
void stop_RU(int nb_ru);
void do_ru_sync(RU_t *ru);

99
100
void configure_ru(int idx, void *arg);
void configure_rru(int idx, void *arg);
Thomas Laurent's avatar
Thomas Laurent committed
101
102
int attach_rru(RU_t *ru);
int connect_rau(RU_t *ru);
103
static void NRRCconfig_RU(void);
Thomas Laurent's avatar
Thomas Laurent committed
104

105
uint16_t sf_ahead;
MaheshK1995's avatar
MaheshK1995 committed
106
uint16_t slot_ahead;
107
uint16_t sl_ahead;
Thomas Laurent's avatar
Thomas Laurent committed
108
109
110
111
112
113
114
115
116

extern int emulate_rf;
extern int numerology;

/*************************************************************/
/* Functions to attach and configure RRU                     */

extern void wait_gNBs(void);

117
int attach_rru(RU_t *ru) {
Thomas Laurent's avatar
Thomas Laurent committed
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
  ssize_t      msg_len,len;
  RRU_CONFIG_msg_t rru_config_msg;
  int received_capabilities=0;
  wait_gNBs();

  // Wait for capabilities
  while (received_capabilities==0) {
    memset((void *)&rru_config_msg,0,sizeof(rru_config_msg));
    rru_config_msg.type = RAU_tick;
    rru_config_msg.len  = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE;
    LOG_I(PHY,"Sending RAU tick to RRU %d\n",ru->idx);
    AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),
                "RU %d cannot access remote radio\n",ru->idx);
    msg_len  = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_capabilities_t);

    // wait for answer with timeout
    if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice,
               &rru_config_msg,
               msg_len))<0) {
      LOG_I(PHY,"Waiting for RRU %d\n",ru->idx);
    } else if (rru_config_msg.type == RRU_capabilities) {
      AssertFatal(rru_config_msg.len==msg_len,"Received capabilities with incorrect length (%d!=%d)\n",(int)rru_config_msg.len,(int)msg_len);
      LOG_I(PHY,"Received capabilities from RRU %d (len %d/%d, num_bands %d,max_pdschReferenceSignalPower %d, max_rxgain %d, nb_tx %d, nb_rx %d)\n",ru->idx,
            (int)rru_config_msg.len,(int)msg_len,
            ((RRU_capabilities_t *)&rru_config_msg.msg[0])->num_bands,
            ((RRU_capabilities_t *)&rru_config_msg.msg[0])->max_pdschReferenceSignalPower[0],
            ((RRU_capabilities_t *)&rru_config_msg.msg[0])->max_rxgain[0],
            ((RRU_capabilities_t *)&rru_config_msg.msg[0])->nb_tx[0],
            ((RRU_capabilities_t *)&rru_config_msg.msg[0])->nb_rx[0]);
      received_capabilities=1;
    } else {
      LOG_E(PHY,"Received incorrect message %d from RRU %d\n",rru_config_msg.type,ru->idx);
    }
  }

  configure_ru(ru->idx,
               (RRU_capabilities_t *)&rru_config_msg.msg[0]);
  rru_config_msg.type = RRU_config;
  rru_config_msg.len  = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_config_t);
  LOG_I(PHY,"Sending Configuration to RRU %d (num_bands %d,band0 %d,txfreq %u,rxfreq %u,att_tx %d,att_rx %d,N_RB_DL %d,N_RB_UL %d,3/4FS %d, prach_FO %d, prach_CI %d)\n",ru->idx,
        ((RRU_config_t *)&rru_config_msg.msg[0])->num_bands,
        ((RRU_config_t *)&rru_config_msg.msg[0])->band_list[0],
        ((RRU_config_t *)&rru_config_msg.msg[0])->tx_freq[0],
        ((RRU_config_t *)&rru_config_msg.msg[0])->rx_freq[0],
        ((RRU_config_t *)&rru_config_msg.msg[0])->att_tx[0],
        ((RRU_config_t *)&rru_config_msg.msg[0])->att_rx[0],
        ((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_DL[0],
        ((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_UL[0],
        ((RRU_config_t *)&rru_config_msg.msg[0])->threequarter_fs[0],
        ((RRU_config_t *)&rru_config_msg.msg[0])->prach_FreqOffset[0],
        ((RRU_config_t *)&rru_config_msg.msg[0])->prach_ConfigIndex[0]);
  AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),
              "RU %d failed send configuration to remote radio\n",ru->idx);
171
172
173
174
175
176
177
178
179
180
181

  if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice,
             &rru_config_msg,
             msg_len))<0) {
    LOG_I(PHY,"Waiting for RRU %d\n",ru->idx);
  } else if (rru_config_msg.type == RRU_config_ok) {
    LOG_I(PHY, "RRU_config_ok received\n");
  } else {
    LOG_E(PHY,"Received incorrect message %d from RRU %d\n",rru_config_msg.type,ru->idx);
  }

Thomas Laurent's avatar
Thomas Laurent committed
182
183
184
  return 0;
}

185
int connect_rau(RU_t *ru) {
Thomas Laurent's avatar
Thomas Laurent committed
186
  RRU_CONFIG_msg_t   rru_config_msg;
187
  ssize_t            msg_len;
Thomas Laurent's avatar
Thomas Laurent committed
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
  int                tick_received          = 0;
  int                configuration_received = 0;
  RRU_capabilities_t *cap;
  int                i;
  int                len;

  // wait for RAU_tick
  while (tick_received == 0) {
    msg_len  = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE;

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

  // send capabilities
  rru_config_msg.type = RRU_capabilities;
  rru_config_msg.len  = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_capabilities_t);
  cap                 = (RRU_capabilities_t *)&rru_config_msg.msg[0];
  LOG_I(PHY,"Sending Capabilities (len %d, num_bands %d,max_pdschReferenceSignalPower %d, max_rxgain %d, nb_tx %d, nb_rx %d)\n",
        (int)rru_config_msg.len,ru->num_bands,ru->max_pdschReferenceSignalPower,ru->max_rxgain,ru->nb_tx,ru->nb_rx);

  switch (ru->function) {
    case NGFI_RRU_IF4p5:
219
      cap->FH_fmt                                 = OAI_IF4p5_only;
Thomas Laurent's avatar
Thomas Laurent committed
220
221
222
      break;

    case NGFI_RRU_IF5:
223
      cap->FH_fmt                                 = OAI_IF5_only;
Thomas Laurent's avatar
Thomas Laurent committed
224
225
226
      break;

    case MBP_RRU_IF5:
227
      cap->FH_fmt                                 = MBP_IF5;
Thomas Laurent's avatar
Thomas Laurent committed
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
      break;

    default:
      AssertFatal(1==0,"RU_function is unknown %d\n",RC.ru[0]->function);
      break;
  }

  cap->num_bands                                  = ru->num_bands;

  for (i=0; i<ru->num_bands; i++) {
    LOG_I(PHY,"Band %d: nb_rx %d nb_tx %d pdschReferenceSignalPower %d rxgain %d\n",
          ru->band[i],ru->nb_rx,ru->nb_tx,ru->max_pdschReferenceSignalPower,ru->max_rxgain);
    cap->band_list[i]                             = ru->band[i];
    cap->nb_rx[i]                                 = ru->nb_rx;
    cap->nb_tx[i]                                 = ru->nb_tx;
    cap->max_pdschReferenceSignalPower[i]         = ru->max_pdschReferenceSignalPower;
    cap->max_rxgain[i]                            = ru->max_rxgain;
  }

  AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),
              "RU %d failed send capabilities to RAU\n",ru->idx);
  // wait for configuration
  rru_config_msg.len  = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_config_t);

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

  return 0;
}
/*************************************************************/
/* Southbound Fronthaul functions, RCC/RAU                   */

// southbound IF5 fronthaul for 16-bit OAI format
282
void fh_if5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) {
Thomas Laurent's avatar
Thomas Laurent committed
283
284
  if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );

285
  send_IF5(ru, timestamp, slot, &ru->seqno, IF5_RRH_GW_DL);
Thomas Laurent's avatar
Thomas Laurent committed
286
287
288
}

// southbound IF4p5 fronthaul
289
void fh_if4p5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) {
290
  nfapi_nr_config_request_scf_t *cfg = &ru->config;
291

Thomas Laurent's avatar
Thomas Laurent committed
292
293
294
295
  if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );

  LOG_D(PHY,"Sending IF4p5 for frame %d subframe %d\n",ru->proc.frame_tx,ru->proc.tti_tx);

296
  if ((nr_slot_select(cfg,ru->proc.frame_tx,ru->proc.tti_tx)&NR_DOWNLINK_SLOT) > 0)
297
    send_IF4p5(ru,frame, slot, IF4p5_PDLFFT);
Thomas Laurent's avatar
Thomas Laurent committed
298
299
300
301
302
303
}

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

// Synchronous if5 from south
304
305
void fh_if5_south_in(RU_t *ru,
                     int *frame,
306
                     int *tti) {
Thomas Laurent's avatar
Thomas Laurent committed
307
308
309
  NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
  RU_proc_t *proc = &ru->proc;
  recv_IF5(ru, &proc->timestamp_rx, *tti, IF5_RRH_GW_UL);
310
311
  proc->frame_rx    = (proc->timestamp_rx / (fp->samples_per_subframe*10))&1023;
  uint32_t idx_sf = proc->timestamp_rx / fp->samples_per_subframe;
Sakthivel Velumani's avatar
Sakthivel Velumani committed
312
  proc->tti_rx = (idx_sf * fp->slots_per_subframe + (int)round((float)(proc->timestamp_rx % fp->samples_per_subframe) / fp->samples_per_slot0))%(fp->slots_per_frame);
Thomas Laurent's avatar
Thomas Laurent committed
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333

  if (proc->first_rx == 0) {
    if (proc->tti_rx != *tti) {
      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,*tti);
      exit_fun("Exiting");
    }

    if (proc->frame_rx != *frame) {
      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);
      exit_fun("Exiting");
    }
  } else {
    proc->first_rx = 0;
    *frame = proc->frame_rx;
    *tti = proc->tti_rx;
  }

  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
}

// Synchronous if4p5 from south
334
335
void fh_if4p5_south_in(RU_t *ru,
                       int *frame,
336
                       int *slot) {
Thomas Laurent's avatar
Thomas Laurent committed
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
  NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
  RU_proc_t *proc = &ru->proc;
  int f,sl;
  uint16_t packet_type;
  uint32_t symbol_number=0;
  uint32_t symbol_mask_full=0;

  /*
    if ((fp->frame_type == TDD) && (subframe_select(fp,*slot)==SF_S))
      symbol_mask_full = (1<<fp->ul_symbols_in_S_subframe)-1;
    else
      symbol_mask_full = (1<<fp->symbols_per_slot)-1;

    AssertFatal(proc->symbol_mask[*slot]==0,"rx_fh_if4p5: proc->symbol_mask[%d] = %x\n",*slot,proc->symbol_mask[*slot]);*/
  do {   // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!!
    recv_IF4p5(ru, &f, &sl, &packet_type, &symbol_number);

    if (packet_type == IF4p5_PULFFT) proc->symbol_mask[sl] = proc->symbol_mask[sl] | (1<<symbol_number);
    else if (packet_type == IF4p5_PULTICK) {
      if ((proc->first_rx==0) && (f!=*frame)) LOG_E(PHY,"rx_fh_if4p5: PULTICK received frame %d != expected %d\n",f,*frame);

      if ((proc->first_rx==0) && (sl!=*slot)) LOG_E(PHY,"rx_fh_if4p5: PULTICK received subframe %d != expected %d (first_rx %d)\n",sl,*slot,proc->first_rx);

      break;
    } else if (packet_type == IF4p5_PRACH) {
      // nothing in RU for RAU
    }

    LOG_D(PHY,"rx_fh_if4p5: subframe %d symbol mask %x\n",*slot,proc->symbol_mask[sl]);
  } while(proc->symbol_mask[sl] != symbol_mask_full);

  //caculate timestamp_rx, timestamp_tx based on frame and subframe
369
370
  proc->tti_rx   = sl;
  proc->frame_rx = f;
371
  proc->timestamp_rx = (proc->frame_rx * fp->samples_per_subframe * 10)  + fp->get_samples_slot_timestamp(proc->tti_rx, fp, 0);
Thomas Laurent's avatar
Thomas Laurent committed
372
  //  proc->timestamp_tx = proc->timestamp_rx +  (4*fp->samples_per_subframe);
373
374
  proc->tti_tx   = (sl+(fp->slots_per_subframe*sf_ahead))%fp->slots_per_frame;
  proc->frame_tx = (sl>(fp->slots_per_frame-1-(fp->slots_per_subframe*sf_ahead))) ? (f+1)&1023 : f;
Thomas Laurent's avatar
Thomas Laurent committed
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480

  if (proc->first_rx == 0) {
    if (proc->tti_rx != *slot) {
      LOG_E(PHY,"Received Timestamp (IF4p5) doesn't correspond to the time we think it is (proc->tti_rx %d, subframe %d)\n",proc->tti_rx,*slot);
      exit_fun("Exiting");
    }

    if (proc->frame_rx != *frame) {
      LOG_E(PHY,"Received Timestamp (IF4p5) doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,*frame);
      exit_fun("Exiting");
    }
  } else {
    proc->first_rx = 0;
    *frame = proc->frame_rx;
    *slot = proc->tti_rx;
  }

  if (ru == RC.ru[0]) {
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_RU, f );
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_RX0_RU,  sl);
    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_tx );
  }

  proc->symbol_mask[proc->tti_rx] = 0;
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
  LOG_D(PHY,"RU %d: fh_if4p5_south_in sleeping ...\n",ru->idx);
}

// asynchronous inbound if4p5 fronthaul from south
void fh_if4p5_south_asynch_in(RU_t *ru,int *frame,int *slot) {
  NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
  RU_proc_t *proc       = &ru->proc;
  uint16_t packet_type;
  uint32_t symbol_number,symbol_mask,prach_rx;
  //  uint32_t got_prach_info=0;
  symbol_number = 0;
  symbol_mask   = (1<<(fp->symbols_per_slot))-1;
  prach_rx      = 0;

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

    // grab first prach information for this new subframe
    /*if (got_prach_info==0) {
      prach_rx       = is_prach_subframe(fp, proc->frame_rx, proc->tti_rx);
      got_prach_info = 1;
    }*/
    if (proc->first_rx != 0) {
      *frame = proc->frame_rx;
      *slot = proc->tti_rx;
      proc->first_rx = 0;
    } else {
      if (proc->frame_rx != *frame) {
        LOG_E(PHY,"frame_rx %d is not what we expect %d\n",proc->frame_rx,*frame);
        exit_fun("Exiting");
      }

      if (proc->tti_rx != *slot) {
        LOG_E(PHY,"tti_rx %d is not what we expect %d\n",proc->tti_rx,*slot);
        exit_fun("Exiting");
      }
    }

    if      (packet_type == IF4p5_PULFFT)       symbol_mask &= (~(1<<symbol_number));
    else if (packet_type == IF4p5_PRACH)        prach_rx    &= (~0x1);
  } while( (symbol_mask > 0) || (prach_rx >0));   // haven't received all PUSCH symbols and PRACH information
}





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

// RRU IF4p5 TX fronthaul receiver. Assumes an if_device on input and if or rf device on output
// receives one subframe's worth of IF4p5 OFDM symbols and OFDM modulates
void fh_if4p5_north_in(RU_t *ru,int *frame,int *slot) {
  uint32_t symbol_number=0;
  uint32_t symbol_mask, symbol_mask_full;
  uint16_t packet_type;
  /// **** incoming IF4p5 from remote RCC/RAU **** ///
  symbol_number = 0;
  symbol_mask = 0;
  symbol_mask_full = (1<<(ru->nr_frame_parms->symbols_per_slot))-1;

  do {
    recv_IF4p5(ru, frame, slot, &packet_type, &symbol_number);
    symbol_mask = symbol_mask | (1<<symbol_number);
  } while (symbol_mask != symbol_mask_full);

  // dump VCD output for first RU in list
  if (ru == RC.ru[0]) {
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, *frame );
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, *slot );
  }
}

void fh_if5_north_asynch_in(RU_t *ru,int *frame,int *slot) {
  NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
  RU_proc_t *proc        = &ru->proc;
  int tti_tx,frame_tx;
  openair0_timestamp timestamp_tx;
  recv_IF5(ru, &timestamp_tx, *slot, IF5_RRH_GW_DL);
  //      printf("Received subframe %d (TS %llu) from RCC\n",tti_tx,timestamp_tx);
481
482
  frame_tx    = (timestamp_tx / (fp->samples_per_subframe*10))&1023;
  uint32_t idx_sf = timestamp_tx / fp->samples_per_subframe;
Sakthivel Velumani's avatar
Sakthivel Velumani committed
483
  tti_tx = (idx_sf * fp->slots_per_subframe + (int)round((float)(timestamp_tx % fp->samples_per_subframe) / fp->samples_per_slot0))%(fp->slots_per_frame);
Thomas Laurent's avatar
Thomas Laurent committed
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498

  if (proc->first_tx != 0) {
    *slot = tti_tx;
    *frame    = frame_tx;
    proc->first_tx = 0;
  } else {
    AssertFatal(tti_tx == *slot,
                "tti_tx %d is not what we expect %d\n",tti_tx,*slot);
    AssertFatal(frame_tx == *frame,
                "frame_tx %d is not what we expect %d\n",frame_tx,*frame);
  }
}

void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *slot) {
  NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
499
  nfapi_nr_config_request_scf_t *cfg = &ru->config;
Thomas Laurent's avatar
Thomas Laurent committed
500
501
502
503
504
505
506
507
508
509
510
511
  RU_proc_t *proc        = &ru->proc;
  uint16_t packet_type;
  uint32_t symbol_number,symbol_mask,symbol_mask_full=0;
  int slot_tx,frame_tx;
  LOG_D(PHY, "%s(ru:%p frame, subframe)\n", __FUNCTION__, ru);
  symbol_number = 0;
  symbol_mask = 0;

  //  symbol_mask_full = ((subframe_select(fp,*slot) == SF_S) ? (1<<fp->dl_symbols_in_S_subframe) : (1<<fp->symbols_per_slot))-1;
  do {
    recv_IF4p5(ru, &frame_tx, &slot_tx, &packet_type, &symbol_number);

512
    if (((nr_slot_select(cfg,frame_tx,slot_tx) & NR_DOWNLINK_SLOT) > 0) && (symbol_number == 0)) start_meas(&ru->rx_fhaul);
Thomas Laurent's avatar
Thomas Laurent committed
513

514
    LOG_D(PHY,"slot %d (%d): frame %d, slot %d, symbol %d\n",
515
          *slot,nr_slot_select(cfg,frame_tx,*slot),frame_tx,slot_tx,symbol_number);
Thomas Laurent's avatar
Thomas Laurent committed
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533

    if (proc->first_tx != 0) {
      *frame         = frame_tx;
      *slot          = slot_tx;
      proc->first_tx = 0;
      //symbol_mask_full = ((subframe_select(fp,*slot) == SF_S) ? (1<<fp->dl_symbols_in_S_subframe) : (1<<fp->symbols_per_slot))-1;
    } else {
      AssertFatal(frame_tx == *frame,
                  "frame_tx %d is not what we expect %d\n",frame_tx,*frame);
      AssertFatal(slot_tx == *slot,
                  "slot_tx %d is not what we expect %d\n",slot_tx,*slot);
    }

    if (packet_type == IF4p5_PDLFFT) {
      symbol_mask = symbol_mask | (1<<symbol_number);
    } else AssertFatal(1==0,"Illegal IF4p5 packet type (should only be IF4p5_PDLFFT%d\n",packet_type);
  } while (symbol_mask != symbol_mask_full);

534
  if ((nr_slot_select(cfg,frame_tx,slot_tx) & NR_DOWNLINK_SLOT)>0) stop_meas(&ru->rx_fhaul);
Thomas Laurent's avatar
Thomas Laurent committed
535

536
537
  proc->tti_tx = slot_tx;
  proc->frame_tx = frame_tx;
Thomas Laurent's avatar
Thomas Laurent committed
538
539
540

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

541
  proc->timestamp_tx = (((uint64_t)frame_tx + (uint64_t)proc->frame_tx_unwrap) * fp->samples_per_subframe * 10) + fp->get_samples_slot_timestamp(slot_tx, fp, 0);
Thomas Laurent's avatar
Thomas Laurent committed
542
543
544
545
546
547
548
549
  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,slot_tx);

  // dump VCD output for first RU in list
  if (ru == RC.ru[0]) {
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame_tx );
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, slot_tx );
  }

550
  if (ru->feptx_ofdm) ru->feptx_ofdm(ru,frame_tx,slot_tx);
Thomas Laurent's avatar
Thomas Laurent committed
551

552
  if (ru->fh_south_out) ru->fh_south_out(ru,frame_tx,slot_tx,proc->timestamp_tx);
Thomas Laurent's avatar
Thomas Laurent committed
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
}

void fh_if5_north_out(RU_t *ru) {
  RU_proc_t *proc=&ru->proc;
  uint8_t seqno=0;
  /// **** send_IF5 of rxdata to BBU **** ///
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 );
  send_IF5(ru, proc->timestamp_rx, proc->tti_rx, &seqno, IF5_RRH_GW_UL);
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 );
}

// RRU IF4p5 northbound interface (RX)
void fh_if4p5_north_out(RU_t *ru) {
  RU_proc_t *proc=&ru->proc;

  //NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
  //const int subframe     = proc->tti_rx;
  if (ru->idx==0) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_RX0_RU, proc->tti_rx );

  /*
    if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) {
      /// **** in TDD during DL send_IF4 of ULTICK to RCC **** ///
      send_IF4p5(ru, proc->frame_rx, proc->tti_rx, IF4p5_PULTICK);
      return;
    }*/
  start_meas(&ru->tx_fhaul);
  send_IF4p5(ru, proc->frame_rx, proc->tti_rx, IF4p5_PULFFT);
  stop_meas(&ru->tx_fhaul);
}

knopp's avatar
knopp committed
583
void *emulatedRF_thread(void *param) {
Thomas Laurent's avatar
Thomas Laurent committed
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
  RU_proc_t *proc = (RU_proc_t *) param;
  int microsec = 500; // length of time to sleep, in miliseconds
  struct timespec req = {0};
  req.tv_sec = 0;
  req.tv_nsec = (numerology>0)? ((microsec * 1000L)/numerology):(microsec * 1000L)*2;
  wait_sync("emulatedRF_thread");

  while(!oai_exit) {
    nanosleep(&req, (struct timespec *)NULL);
    pthread_mutex_lock(&proc->mutex_emulateRF);
    ++proc->instance_cnt_emulateRF;
    pthread_mutex_unlock(&proc->mutex_emulateRF);
    pthread_cond_signal(&proc->cond_emulateRF);
  }

  return 0;
}

void rx_rf(RU_t *ru,int *frame,int *slot) {
  RU_proc_t *proc = &ru->proc;
  NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
  void *rxp[ru->nb_rx];
  unsigned int rxs;
  int i;
608
  uint32_t samples_per_slot = fp->get_samples_per_slot(*slot,fp);
609
  uint32_t samples_per_slot_prev ;
Thomas Laurent's avatar
Thomas Laurent committed
610
611
612
613
  openair0_timestamp ts,old_ts;
  AssertFatal(*slot<fp->slots_per_frame && *slot>=0, "slot %d is illegal (%d)\n",*slot,fp->slots_per_frame);

  for (i=0; i<ru->nb_rx; i++)
614
    rxp[i] = (void *)&ru->common.rxdata[i][fp->get_samples_slot_timestamp(*slot,fp,0)];
Thomas Laurent's avatar
Thomas Laurent committed
615
616
617

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 );
  old_ts = proc->timestamp_rx;
618
  LOG_D(PHY,"Reading %d samples for slot %d (%p)\n",samples_per_slot,*slot,rxp[0]);
Thomas Laurent's avatar
Thomas Laurent committed
619
620
621
622

  if(emulate_rf) {
    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");
623
    rxs = samples_per_slot;
Thomas Laurent's avatar
Thomas Laurent committed
624
625
626
627
628
    ts = old_ts + rxs;
  } else {
    rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
                                     &ts,
                                     rxp,
629
                                     samples_per_slot,
Thomas Laurent's avatar
Thomas Laurent committed
630
631
632
633
634
635
636
637
                                     ru->nb_rx);
  }

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
  proc->timestamp_rx = ts-ru->ts_offset;

  //AssertFatal(rxs == fp->samples_per_subframe,
  //"rx_rf: Asked for %d samples, got %d from USRP\n",fp->samples_per_subframe,rxs);
638
  if (rxs != samples_per_slot) LOG_E(PHY, "rx_rf: Asked for %d samples, got %d from USRP\n",samples_per_slot,rxs);
Thomas Laurent's avatar
Thomas Laurent committed
639
640
641
642
643

  if (proc->first_rx == 1) {
    ru->ts_offset = proc->timestamp_rx;
    proc->timestamp_rx = 0;
  } else {
644
    samples_per_slot_prev = fp->get_samples_per_slot((*slot-1)%fp->slots_per_frame,fp);
645

646
647
648
    if (proc->timestamp_rx - old_ts != samples_per_slot_prev) {
      LOG_D(PHY,"rx_rf: rfdevice timing drift of %"PRId64" samples (ts_off %"PRId64")\n",proc->timestamp_rx - old_ts - samples_per_slot_prev,ru->ts_offset);
      ru->ts_offset += (proc->timestamp_rx - old_ts - samples_per_slot_prev);
Thomas Laurent's avatar
Thomas Laurent committed
649
650
651
652
      proc->timestamp_rx = ts-ru->ts_offset;
    }
  }

653
  proc->frame_rx    = (proc->timestamp_rx / (fp->samples_per_subframe*10))&1023;
654
  proc->tti_rx = fp->get_slot_from_timestamp(proc->timestamp_rx,fp);
Thomas Laurent's avatar
Thomas Laurent committed
655
  // synchronize first reception to frame 0 subframe 0
656
  LOG_D(PHY,"RU %d/%d TS %llu (off %d), frame %d, slot %d.%d / %d\n",
Thomas Laurent's avatar
Thomas Laurent committed
657
658
659
660
661
662
663
664
665
666
667
668
669
        ru->idx,
        0,
        (unsigned long long int)proc->timestamp_rx,
        (int)ru->ts_offset,proc->frame_rx,proc->tti_rx,proc->tti_tx,fp->slots_per_frame);

  // dump VCD output for first RU in list
  if (ru == RC.ru[0]) {
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_RU, proc->frame_rx );
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_RX0_RU, proc->tti_rx );
  }

  if (proc->first_rx == 0) {
    if (proc->tti_rx != *slot) {
670
      LOG_E(PHY,"Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->tti_rx %d, slot %d)\n",(long long unsigned int)proc->timestamp_rx,proc->tti_rx,*slot);
Thomas Laurent's avatar
Thomas Laurent committed
671
672
673
674
      exit_fun("Exiting");
    }

    if (proc->frame_rx != *frame) {
675
676
      LOG_E(PHY,"Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->frame_rx %d frame %d, proc->tti_rx %d, slot %d)\n",(long long unsigned int)proc->timestamp_rx,proc->frame_rx,
            *frame,proc->tti_rx,*slot);
Thomas Laurent's avatar
Thomas Laurent committed
677
678
679
680
681
682
683
684
685
686
687
      exit_fun("Exiting");
    }
  } else {
    proc->first_rx = 0;
    *frame = proc->frame_rx;
    *slot  = proc->tti_rx;
  }

  //printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",ru->timestamp_rx,proc->frame_rx,frame,proc->tti_rx,subframe);
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );

688
  if (rxs != samples_per_slot) {
Thomas Laurent's avatar
Thomas Laurent committed
689
690
691
692
693
694
    //exit_fun( "problem receiving samples" );
    LOG_E(PHY, "problem receiving samples\n");
  }
}


Thomas Laurent's avatar
Thomas Laurent committed
695
void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) {
Thomas Laurent's avatar
Thomas Laurent committed
696
697
  RU_proc_t *proc = &ru->proc;
  NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
698
  nfapi_nr_config_request_scf_t *cfg = &ru->config;
Thomas Laurent's avatar
Thomas Laurent committed
699
700
  void *txp[ru->nb_tx];
  unsigned int txs;
701
  int i,txsymb;
702
  T(T_ENB_PHY_OUTPUT_SIGNAL, T_INT(0), T_INT(0), T_INT(frame), T_INT(slot),
Sakthivel Velumani's avatar
Sakthivel Velumani committed
703
    T_INT(0), T_BUFFER(&ru->common.txdata[0][fp->get_samples_slot_timestamp(slot,fp,0)], fp->samples_per_subframe * 4));
knopp's avatar
knopp committed
704
705
706
  int slot_type         = nr_slot_select(cfg,frame,slot%fp->slots_per_frame);
  int prevslot_type     = nr_slot_select(cfg,frame,(slot+(fp->slots_per_frame-1))%fp->slots_per_frame);
  int nextslot_type     = nr_slot_select(cfg,frame,(slot+1)%fp->slots_per_frame);
707
  int sf_extension  = 0;                 //sf_extension = ru->sf_extension;
708
  int siglen=fp->get_samples_per_slot(slot,fp);
Francesco Mani's avatar
Francesco Mani committed
709
710
  int flags=1;

Florian Kaltenberger's avatar
Florian Kaltenberger committed
711
  //nr_subframe_t SF_type     = nr_slot_select(cfg,slot%fp->slots_per_frame);
712
  if (slot_type == NR_DOWNLINK_SLOT || slot_type == NR_MIXED_SLOT || IS_SOFTMODEM_RFSIM) {
713
    if (cfg->cell_config.frame_duplex_type.value == TDD) {
714
715
      if(slot_type == NR_MIXED_SLOT) {
        txsymb = 0;
716

717
718
719
720
        for(int symbol_count = 0; symbol_count<NR_NUMBER_OF_SYMBOLS_PER_SLOT; symbol_count++) {
          if (cfg->tdd_table.max_tdd_periodicity_list[slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value == 0)
            txsymb++;
        }
721

722
        AssertFatal(txsymb>0,"illegal txsymb %d\n",txsymb);
723

724
725
726
727
        if(slot%(fp->slots_per_subframe/2))
          siglen = txsymb * (fp->ofdm_symbol_size + fp->nb_prefix_samples);
        else
          siglen = (fp->ofdm_symbol_size + fp->nb_prefix_samples0) + (txsymb - 1) * (fp->ofdm_symbol_size + fp->nb_prefix_samples);
728
729

        //+ ru->end_of_burst_delay;
730
        flags = 3; // end of burst
Francesco Mani's avatar
Francesco Mani committed
731
      }
rakesh mundlamuri's avatar
rakesh mundlamuri committed
732

733
734
      if (slot_type == NR_DOWNLINK_SLOT && prevslot_type == NR_UPLINK_SLOT)
        flags = 2; // start of burst
knopp's avatar
knopp committed
735

736
737
      if (slot_type == NR_DOWNLINK_SLOT && nextslot_type == NR_UPLINK_SLOT)
        flags = 3; // end of burst
knopp's avatar
knopp committed
738
    }
739

740
    if (fp->freq_range==nr_FR2) {
741
742
      // the beam index is written in bits 8-10 of the flags
      // bit 11 enables the gpio programming
743
      // currently we switch beams every 10 slots (should = 1 TDD period in FR2) and we take the beam index of the first symbol of the first slot of this period
744
      int beam=0;
745

746
      if (slot%10==0) {
747
        if ( ru->common.beam_id && (ru->common.beam_id[0][slot*fp->symbols_per_slot] < 8)) {
748
749
          beam = ru->common.beam_id[0][slot*fp->symbols_per_slot] | 8;
        }
750
      }
751

Florian Kaltenberger's avatar
Florian Kaltenberger committed
752
      /*
753
754
755
756
      if (slot==0 || slot==40) beam=0|8;
      if (slot==10 || slot==50) beam=1|8;
      if (slot==20 || slot==60) beam=2|8;
      if (slot==30 || slot==70) beam=3|8;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
757
      */
758
      flags |= beam<<8;
Francesco Mani's avatar
Francesco Mani committed
759
      LOG_D(HW,"slot %d, beam %d\n",slot,ru->common.beam_id[0][slot*fp->symbols_per_slot]);
760
    }
761
762

    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_WRITE_FLAGS, flags );
763
764
    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, slot );
765

766
    for (i=0; i<ru->nb_tx; i++)
767
      txp[i] = (void *)&ru->common.txdata[i][fp->get_samples_slot_timestamp(slot,fp,0)-sf_extension];
768
769
770
771
772
773
774
775
776
777
778
779
780
781

    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp-ru->openair0_cfg.tx_sample_advance)&0xffffffff );
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
    // prepare tx buffer pointers
    txs = ru->rfdevice.trx_write_func(&ru->rfdevice,
                                      timestamp+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension,
                                      txp,
                                      siglen+sf_extension,
                                      ru->nb_tx,
                                      flags);
    LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, unwrapped_frame %d, slot %di, returned %d\n",ru->idx,
          (long long unsigned int)timestamp,frame,proc->frame_tx_unwrap,slot, txs);
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
    //AssertFatal(txs == 0,"trx write function error %d\n", txs);
782
  }
Thomas Laurent's avatar
Thomas Laurent committed
783
784
785
786
787
788
}

// this is for RU with local RF unit
void fill_rf_config(RU_t *ru, char *rf_config_file) {
  int i;
  NR_DL_FRAME_PARMS *fp   = ru->nr_frame_parms;
789
  nfapi_nr_config_request_scf_t *config = &ru->config; //tmp index
Thomas Laurent's avatar
Thomas Laurent committed
790
  openair0_config_t *cfg   = &ru->openair0_cfg;
791
792
  int mu = config->ssb_config.scs_common.value;
  int N_RB = config->carrier_config.dl_grid_size[config->ssb_config.scs_common.value].value;
Thomas Laurent's avatar
Thomas Laurent committed
793

794
795
  if (mu == NR_MU_0) {
    switch(N_RB) {
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
      case 270:
        if (fp->threequarter_fs) {
          cfg->sample_rate=92.16e6;
          cfg->samples_per_frame = 921600;
          cfg->tx_bw = 50e6;
          cfg->rx_bw = 50e6;
        } else {
          cfg->sample_rate=61.44e6;
          cfg->samples_per_frame = 614400;
          cfg->tx_bw = 50e6;
          cfg->rx_bw = 50e6;
        }

      case 216:
        if (fp->threequarter_fs) {
          cfg->sample_rate=46.08e6;
          cfg->samples_per_frame = 460800;
          cfg->tx_bw = 40e6;
          cfg->rx_bw = 40e6;
        } else {
          cfg->sample_rate=61.44e6;
          cfg->samples_per_frame = 614400;
          cfg->tx_bw = 40e6;
          cfg->rx_bw = 40e6;
        }

        break;

      case 106:
        if (fp->threequarter_fs) {
          cfg->sample_rate=23.04e6;
          cfg->samples_per_frame = 230400;
          cfg->tx_bw = 20e6;
          cfg->rx_bw = 20e6;
        } else {
          cfg->sample_rate=30.72e6;
          cfg->samples_per_frame = 307200;
          cfg->tx_bw = 20e6;
          cfg->rx_bw = 20e6;
        }

        break;

      case 52:
        if (fp->threequarter_fs) {
          cfg->sample_rate=11.52e6;
          cfg->samples_per_frame = 115200;
          cfg->tx_bw = 10e6;
          cfg->rx_bw = 10e6;
        } else {
          cfg->sample_rate=15.36e6;
          cfg->samples_per_frame = 153600;
          cfg->tx_bw = 10e6;
          cfg->rx_bw = 10e6;
        }

      case 25:
        if (fp->threequarter_fs) {
          cfg->sample_rate=5.76e6;
          cfg->samples_per_frame = 57600;
          cfg->tx_bw = 5e6;
          cfg->rx_bw = 5e6;
        } else {
          cfg->sample_rate=7.68e6;
          cfg->samples_per_frame = 76800;
          cfg->tx_bw = 5e6;
          cfg->rx_bw = 5e6;
        }

        break;

      default:
        AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu);
869
    }
Thomas Laurent's avatar
Thomas Laurent committed
870
  } else if (mu == NR_MU_1) {
871
    switch(N_RB) {
872

873
    case 273:
WANG Tsu-Han's avatar
WANG Tsu-Han committed
874
      if (fp->threequarter_fs) {
875
876
877
878
        cfg->sample_rate=184.32e6;
        cfg->samples_per_frame = 1843200;
        cfg->tx_bw = 100e6;
        cfg->rx_bw = 100e6;
WANG Tsu-Han's avatar
WANG Tsu-Han committed
879
      } else {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
880
881
        cfg->sample_rate=122.88e6;
        cfg->samples_per_frame = 1228800;
WANG Tsu-Han's avatar
WANG Tsu-Han committed
882
883
884
        cfg->tx_bw = 100e6;
        cfg->rx_bw = 100e6;
      }
885
886
      break;
    case 217:
Thomas Laurent's avatar
Thomas Laurent committed
887
888
889
      if (fp->threequarter_fs) {
        cfg->sample_rate=92.16e6;
        cfg->samples_per_frame = 921600;
WANG Tsu-Han's avatar
WANG Tsu-Han committed
890
891
        cfg->tx_bw = 80e6;
        cfg->rx_bw = 80e6;
Thomas Laurent's avatar
Thomas Laurent committed
892
893
894
      } else {
        cfg->sample_rate=122.88e6;
        cfg->samples_per_frame = 1228800;
WANG Tsu-Han's avatar
WANG Tsu-Han committed
895
896
        cfg->tx_bw = 80e6;
        cfg->rx_bw = 80e6;
Thomas Laurent's avatar
Thomas Laurent committed
897
      }
898
899
900
901
902
903
904
905
906
907
908
      break;
    case 133 :
      if (fp->threequarter_fs) {
	AssertFatal(1==0,"N_RB %d cannot use 3/4 sampling\n",N_RB);
      }
      else {
        cfg->sample_rate=61.44e6;
        cfg->samples_per_frame = 614400;
        cfg->tx_bw = 50e6;
        cfg->rx_bw = 50e6;
      }
909

910
911
      break;
    case 106:
912
      if (fp->threequarter_fs) {
Thomas Laurent's avatar
Thomas Laurent committed
913
914
915
916
        cfg->sample_rate=46.08e6;
        cfg->samples_per_frame = 460800;
        cfg->tx_bw = 40e6;
        cfg->rx_bw = 40e6;
917
918
      }
      else {
Thomas Laurent's avatar
Thomas Laurent committed
919
920
921
922
        cfg->sample_rate=61.44e6;
        cfg->samples_per_frame = 614400;
        cfg->tx_bw = 40e6;
        cfg->rx_bw = 40e6;
923
      }
924
     break;
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
    case 51:
      if (fp->threequarter_fs) {
        cfg->sample_rate=23.04e6;
        cfg->samples_per_frame = 230400;
        cfg->tx_bw = 20e6;
        cfg->rx_bw = 20e6;
      }
      else {
        cfg->sample_rate=30.72e6;
        cfg->samples_per_frame = 307200;
        cfg->tx_bw = 20e6;
        cfg->rx_bw = 20e6;
      }
      break;
    case 24:
940
      if (fp->threequarter_fs) {
941
942
943
944
945
946
        cfg->sample_rate=11.52e6;
        cfg->samples_per_frame = 115200;
        cfg->tx_bw = 10e6;
        cfg->rx_bw = 10e6;
      }
      else {
947
948
949
950
        cfg->sample_rate=15.36e6;
        cfg->samples_per_frame = 153600;
        cfg->tx_bw = 10e6;
        cfg->rx_bw = 10e6;
951
      }
952
953
      break;
    default:
Thomas Laurent's avatar
Thomas Laurent committed
954
955
      AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu);
    }
956
  } else if (mu == NR_MU_3) {
957
    switch(N_RB) {
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
      case 66:
        if (fp->threequarter_fs) {
          cfg->sample_rate=184.32e6;
          cfg->samples_per_frame = 1843200;
          cfg->tx_bw = 100e6;
          cfg->rx_bw = 100e6;
        } else {
          cfg->sample_rate = 122.88e6;
          cfg->samples_per_frame = 1228800;
          cfg->tx_bw = 100e6;
          cfg->rx_bw = 100e6;
        }

        break;

      case 32:
        if (fp->threequarter_fs) {
          cfg->sample_rate=92.16e6;
          cfg->samples_per_frame = 921600;
          cfg->tx_bw = 50e6;
          cfg->rx_bw = 50e6;
        } else {
          cfg->sample_rate=61.44e6;
          cfg->samples_per_frame = 614400;
          cfg->tx_bw = 50e6;
          cfg->rx_bw = 50e6;
        }

        break;

      default:
        AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu);
990
    }
Thomas Laurent's avatar
Thomas Laurent committed
991
992
993
994
  } else {
    AssertFatal(0 == 1,"Numerology %d not supported for the moment\n",mu);
  }

995
  if (config->cell_config.frame_duplex_type.value==TDD)
Thomas Laurent's avatar
Thomas Laurent committed
996
997
998
999
1000
1001
1002
1003
1004
1005
    cfg->duplex_mode = duplex_mode_TDD;
  else //FDD
    cfg->duplex_mode = duplex_mode_FDD;

  cfg->Mod_id = 0;
  cfg->num_rb_dl=N_RB;
  cfg->tx_num_channels=ru->nb_tx;
  cfg->rx_num_channels=ru->nb_rx;

  for (i=0; i<ru->nb_tx; i++) {
1006
1007
1008
    if (ru->if_frequency == 0) {
      cfg->tx_freq[i] = (double)fp->dl_CarrierFreq;
      cfg->rx_freq[i] = (double)fp->ul_CarrierFreq;
1009
    } else if (ru->if_freq_offset) {
1010
1011
1012
1013
      cfg->tx_freq[i] = (double)(ru->if_frequency);
      cfg->rx_freq[i] = (double)(ru->if_frequency + ru->if_freq_offset);
      LOG_I(PHY, "Setting IF TX frequency to %lu Hz with IF RX frequency offset %d Hz\n", ru->if_frequency, ru->if_freq_offset);
    } else {
1014
1015
1016
      cfg->tx_freq[i] = (double)ru->if_frequency;
      cfg->rx_freq[i] = (double)(ru->if_frequency+fp->ul_CarrierFreq-fp->dl_CarrierFreq);
    }
1017

Thomas Laurent's avatar
Thomas Laurent committed
1018
1019
1020
    cfg->tx_gain[i] = ru->att_tx;
    cfg->rx_gain[i] = ru->max_rxgain-ru->att_rx;
    cfg->configFilename = rf_config_file;
1021
    LOG_I(PHY, "Channel %d: setting tx_gain offset %f, rx_gain offset %f, tx_freq %lu Hz, rx_freq %lu Hz\n",
1022
1023
1024
1025
          i, cfg->tx_gain[i],
          cfg->rx_gain[i],
          (unsigned long)cfg->tx_freq[i],
          (unsigned long)cfg->rx_freq[i]);
Thomas Laurent's avatar
Thomas Laurent committed
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
  }
}

/* this function maps the RU tx and rx buffers to the available rf chains.
   Each rf chain is is addressed by the card number and the chain on the card. The
   rf_map specifies for each antenna port, on which rf chain the mapping should start. Multiple
   antennas are mapped to successive RF chains on the same card. */
int setup_RU_buffers(RU_t *ru) {
  int i,j;
  int card,ant;
  //uint16_t N_TA_offset = 0;
1037
  NR_DL_FRAME_PARMS *fp;
1038
  nfapi_nr_config_request_scf_t *config = &ru->config;
Thomas Laurent's avatar
Thomas Laurent committed
1039
1040

  if (ru) {
1041
1042
    fp = ru->nr_frame_parms;
    printf("setup_RU_buffers: frame_parms = %p\n",fp);
Thomas Laurent's avatar
Thomas Laurent committed
1043
  } else {
1044
    printf("ru pointer is NULL\n");
Thomas Laurent's avatar
Thomas Laurent committed
1045
1046
    return(-1);
  }
1047

1048
1049
  int mu = config->ssb_config.scs_common.value;
  int N_RB = config->carrier_config.dl_grid_size[config->ssb_config.scs_common.value].value;
Thomas Laurent's avatar
Thomas Laurent committed
1050

1051
1052
1053
  if (config->cell_config.frame_duplex_type.value == TDD) {
    int N_TA_offset =  config->carrier_config.uplink_frequency.value < 6000000 ? 400 : 431; // reference samples  for 25600Tc @ 30.72 Ms/s for FR1, same @ 61.44 Ms/s for FR2
    double factor=1;
1054

1055
    switch (mu) {
1056
1057
1058
1059
      case 0: //15 kHz scs
        AssertFatal(N_TA_offset == 400, "scs_common 15kHz only for FR1\n");
        factor = fp->samples_per_subframe / 30720.0;
        break;
1060

1061
1062
1063
1064
      case 1: //30 kHz sc
        AssertFatal(N_TA_offset == 400, "scs_common 30kHz only for FR1\n");
        factor = fp->samples_per_subframe / 30720.0;
        break;
1065

1066
1067
1068
      case 2: //60 kHz scs
        AssertFatal(1==0, "scs_common should not be 60 kHz\n");
        break;
1069

1070
1071
1072
1073
      case 3: //120 kHz scs
        AssertFatal(N_TA_offset == 431, "scs_common 120kHz only for FR2\n");
        factor = fp->samples_per_subframe / 61440.0;
        break;
1074

1075
1076
1077
1078
      case 4: //240 kHz scs
        AssertFatal(N_TA_offset == 431, "scs_common 240kHz only for FR2\n");
        factor = fp->samples_per_subframe / 61440.0;
        break;
1079

1080
1081
      default:
        AssertFatal(1==0, "Invalid scs_common!\n");
1082
    }
1083

1084
    ru->N_TA_offset = (int)(N_TA_offset * factor);
1085
    LOG_I(PHY,"RU %d Setting N_TA_offset to %d samples (factor %f, UL Freq %d, N_RB %d, mu %d)\n",ru->idx,ru->N_TA_offset,factor,
1086
1087
          config->carrier_config.uplink_frequency.value, N_RB, mu);
  } else ru->N_TA_offset = 0;
1088

Thomas Laurent's avatar
Thomas Laurent committed
1089
1090
1091
1092
1093
  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;
1094
      printf("Mapping RU id %u, rx_ant %d, on card %d, chain %d\n",ru->idx,i,ru->rf_map.card+card, ru->rf_map.chain+ant);
Thomas Laurent's avatar
Thomas Laurent committed
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
      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]);

      for (j=0; j<16; j++) {
        printf("rxbuffer %d: %x\n",j,ru->common.rxdata[i][j]);
        ru->common.rxdata[i][j] = 16-j;
      }
    }

    for (i=0; i<ru->nb_tx; i++) {
      card = i/4;
      ant = i%4;
1108
      printf("Mapping RU id %u, tx_ant %d, on card %d, chain %d\n",ru->idx,i,ru->rf_map.card+card, ru->rf_map.chain+ant);
Thomas Laurent's avatar
Thomas Laurent committed
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
      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]);

      for (j=0; j<16; j++) {
        printf("txbuffer %d: %x\n",j,ru->common.txdata[i][j]);
        ru->common.txdata[i][j] = 16-j;
      }
    }
  } else { // not memory-mapped DMA
    //nothing to do, everything already allocated in lte_init
  }

  return(0);
}

knopp's avatar
knopp committed
1125
void *ru_stats_thread(void *param) {
Thomas Laurent's avatar
Thomas Laurent committed
1126
1127
1128
1129
1130
1131
1132
1133
1134
  RU_t               *ru      = (RU_t *)param;
  wait_sync("ru_stats_thread");

  while (!oai_exit) {
    sleep(1);

    if (opp_enabled == 1) {
      if (ru->feprx) print_meas(&ru->ofdm_demod_stats,"feprx",NULL,NULL);

Thomas Laurent's avatar
Thomas Laurent committed
1135
      if (ru->feptx_ofdm) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1136
        print_meas(&ru->precoding_stats,"feptx_prec",NULL,NULL);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1137
1138
1139
1140
        print_meas(&ru->txdataF_copy_stats,"txdataF_copy",NULL,NULL);
        print_meas(&ru->ofdm_mod_stats,"feptx_ofdm",NULL,NULL);
        print_meas(&ru->ofdm_total_stats,"feptx_total",NULL,NULL);
      }
Thomas Laurent's avatar
Thomas Laurent committed
1141
1142
1143

      if (ru->fh_north_asynch_in) print_meas(&ru->rx_fhaul,"rx_fhaul",NULL,NULL);

Thomas Laurent's avatar
Thomas Laurent committed
1144
      print_meas(&ru->tx_fhaul,"tx_fhaul",NULL,NULL);
1145

1146
      if (ru->fh_north_out) {
Thomas Laurent's avatar
Thomas Laurent committed
1147
1148
1149
1150
1151
1152
1153
1154
1155
        print_meas(&ru->compression,"compression",NULL,NULL);
        print_meas(&ru->transport,"transport",NULL,NULL);
      }
    }
  }

  return(NULL);
}

Sakthivel Velumani's avatar
Sakthivel Velumani committed
1156
1157
1158
1159
1160
1161
1162
1163
void ru_tx_func(void *param) {
  processingData_RU_t *info = (processingData_RU_t *) param;
  RU_t *ru = info->ru;
  NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
  int frame_tx = info->frame_tx;
  int slot_tx = info->slot_tx;
  int print_frame = 8;
  char filename[40];
Thomas Laurent's avatar
Thomas Laurent committed
1164

Sakthivel Velumani's avatar
Sakthivel Velumani committed
1165
1166
  // do TX front-end processing if needed (precoding and/or IDFTs)
  if (ru->feptx_prec) ru->feptx_prec(ru,frame_tx,slot_tx);
Thomas Laurent's avatar
Thomas Laurent committed
1167

Sakthivel Velumani's avatar
Sakthivel Velumani committed
1168
1169
  // do OFDM with/without TX front-end processing  if needed
  if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,frame_tx,slot_tx);
Thomas Laurent's avatar
Thomas Laurent committed
1170

Sakthivel Velumani's avatar
Sakthivel Velumani committed
1171
1172
  if(!emulate_rf) {
    // do outgoing fronthaul (south) if needed
1173
    if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,frame_tx,slot_tx,info->timestamp_tx);
1174

Sakthivel Velumani's avatar
Sakthivel Velumani committed
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
    if (ru->fh_north_out) ru->fh_north_out(ru);
  } else {
    if(frame_tx == print_frame) {
      for (int i=0; i<ru->nb_tx; i++) {
        if(slot_tx == 0) {
          sprintf(filename,"gNBdataF_frame%d_sl%d.m", print_frame, slot_tx);
          LOG_M(filename,"txdataF_frame",&ru->gNB_list[0]->common_vars.txdataF[i][0],fp->samples_per_frame_wCP, 1, 1);
          sprintf(filename,"tx%ddataF_frame%d_sl%d.m", i, print_frame, slot_tx);
          LOG_M(filename,"txdataF_frame",&ru->common.txdataF[i][0],fp->samples_per_frame_wCP, 1, 1);
          sprintf(filename,"tx%ddataF_BF_frame%d_sl%d.m", i, print_frame, slot_tx);
          LOG_M(filename,"txdataF_BF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_subframe_wCP, 1, 1);
Thomas Laurent's avatar
Thomas Laurent committed
1186
1187
        }

Sakthivel Velumani's avatar
Sakthivel Velumani committed
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
        if(slot_tx == 9) {
          sprintf(filename,"tx%ddata_frame%d.m", i, print_frame);
          LOG_M(filename,"txdata_frame",&ru->common.txdata[i][0],fp->samples_per_frame, 1, 1);
          sprintf(filename,"tx%ddata_frame%d.dat", i, print_frame);
          FILE *output_fd = fopen(filename,"w");

          if (output_fd) {
            fwrite(&ru->common.txdata[i][0],
                   sizeof(int32_t),
                   fp->samples_per_frame,
                   output_fd);
            fclose(output_fd);
          } else {
            LOG_E(PHY,"Cannot write to file %s\n",filename);
          }
        }//if(slot_tx == 9)
      }//for (i=0; i<ru->nb_tx; i++)
    }//if(frame_tx == print_frame)
  }//else  emulate_rf
Thomas Laurent's avatar
Thomas Laurent committed
1207
1208
}

knopp's avatar
knopp committed
1209
void *ru_thread( void *param ) {
Thomas Laurent's avatar
Thomas Laurent committed
1210
1211
1212
  static int ru_thread_status;
  RU_t               *ru      = (RU_t *)param;
  RU_proc_t          *proc    = &ru->proc;
1213
  NR_DL_FRAME_PARMS  *fp      = ru->nr_frame_parms;
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1214
  PHY_VARS_gNB       *gNB     = RC.gNB[0];
Thomas Laurent's avatar
Thomas Laurent committed
1215
  int                ret;
1216
1217
  int                slot     = fp->slots_per_frame-1;
  int                frame    = 1023;
1218
  char               threadname[40];
1219
  int                aa;
1220
  nfapi_nr_config_request_scf_t *cfg = &ru->config;
Thomas Laurent's avatar
Thomas Laurent committed
1221
1222
1223
  // set default return value
  ru_thread_status = 0;
  // set default return value
1224
  sprintf(threadname,"ru_thread %u",ru->idx);
Thomas Laurent's avatar
Thomas Laurent committed
1225
  LOG_I(PHY,"Starting RU %d (%s,%s),\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing]);
1226
  memcpy((void *)&ru->config,(void *)&RC.gNB[0]->gNB_config,sizeof(ru->config));
1227

Thomas Laurent's avatar
Thomas Laurent committed
1228
1229
  if(emulate_rf) {
    fill_rf_config(ru,ru->rf_config_file);
1230
    nr_init_frame_parms(&ru->config, fp);
Thomas Laurent's avatar
Thomas Laurent committed
1231
1232
1233
1234
1235
1236
1237
1238
1239
    nr_dump_frame_parms(fp);
    nr_phy_init_RU(ru);

    if (setup_RU_buffers(ru)!=0) {
      printf("Exiting, cannot initialize RU Buffers\n");
      exit(-1);
    }
  } else {
    // Start IF device if any
1240
    if (ru->nr_start_if) {
Thomas Laurent's avatar
Thomas Laurent committed
1241
      LOG_I(PHY,"Starting IF interface for RU %d\n",ru->idx);
1242
      AssertFatal(ru->nr_start_if(ru,NULL) == 0, "Could not start the IF device\n");
Thomas Laurent's avatar
Thomas Laurent committed
1243
1244
1245
1246
1247
1248
1249
1250

      if (ru->if_south == LOCAL_RF) ret = connect_rau(ru);
      else ret = attach_rru(ru);

      AssertFatal(ret==0,"Cannot connect to remote radio\n");
    }

    if (ru->if_south == LOCAL_RF) { // configure RF parameters only
1251
      nr_init_frame_parms(&ru->config, fp);
Thomas Laurent's avatar
Thomas Laurent committed
1252
      nr_dump_frame_parms(fp);
1253
      fill_rf_config(ru,ru->rf_config_file);
Thomas Laurent's avatar
Thomas Laurent committed
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
      nr_phy_init_RU(ru);
      ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg);
      AssertFatal(ret==0,"Cannot connect to local radio\n");
    }

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

1265
  sf_ahead = (uint16_t) ceil((float)6/(0x01<<fp->numerology_index));
Thomas Laurent's avatar
Thomas Laurent committed
1266
1267
1268
1269
1270
1271
  LOG_I(PHY, "Signaling main thread that RU %d is ready\n",ru->idx);
  pthread_mutex_lock(&RC.ru_mutex);
  RC.ru_mask &= ~(1<<ru->idx);
  pthread_cond_signal(&RC.ru_cond);
  pthread_mutex_unlock(&RC.ru_mutex);
  wait_sync("ru_thread");
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1272
  notifiedFIFO_elt_t *msg = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_L1,rx_func);
1273
1274
1275
  notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_L1_tx,tx_func);
  notifiedFIFO_elt_t *msgRUTx = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_RU_tx,ru_tx_func);
  processingData_L1_t *syncMsg;
1276
  notifiedFIFO_elt_t *res;
1277
1278
1279
  pushNotifiedFIFO(gNB->resp_L1,msg); // to unblock the process in the beginning
  pushNotifiedFIFO(gNB->resp_L1_tx,msgL1Tx); // to unblock the process in the beginning
  pushNotifiedFIFO(gNB->resp_RU_tx,msgRUTx); // to unblock the process in the beginning
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1280

Thomas Laurent's avatar
Thomas Laurent committed
1281
1282
1283
1284
1285
1286
1287
1288
  if(!emulate_rf) {
    // Start RF device if any
    if (ru->start_rf) {
      if (ru->start_rf(ru) != 0)
        LOG_E(HW,"Could not start the RF device\n");
      else LOG_I(PHY,"RU %d rf device ready\n",ru->idx);
    } else LOG_I(PHY,"RU %d no rf device\n",ru->idx);

WANG Tsu-Han's avatar
WANG Tsu-Han committed
1289
    // start trx write thread
1290
1291
1292
    if(usrp_tx_thread == 1) {
      if (ru->start_write_thread) {
        if(ru->start_write_thread(ru) != 0) {
1293
          LOG_E(HW,"Could not start tx write thread\n");
1294
        } else {