prachsim.c 29.8 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/*
 * 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
 */

#include <string.h>
#include <math.h>
#include <unistd.h>
25
#include <pthread.h>
26
27
28
29
30
31
32
33
34
35
36
37
38
39

#include "common/config/config_userapi.h"
#include "common/utils/LOG/log.h"
#include "common/ran_context.h" 

#include "SIMULATION/TOOLS/sim.h"
#include "SIMULATION/RF/rf.h"
#include "PHY/types.h"
#include "PHY/defs_gNB.h"
#include "PHY/defs_nr_UE.h"
#include "SCHED_NR/sched_nr.h"
#include "SCHED_NR_UE/phy_frame_config_nr.h"
#include "PHY/phy_vars_nr_ue.h"
#include "PHY/NR_REFSIG/refsig_defs_ue.h"
40
#include "PHY/MODULATION/nr_modulation.h"
41
42
43
#include "PHY/MODULATION/modulation_eNB.h"
#include "PHY/MODULATION/modulation_UE.h"
#include "PHY/INIT/phy_init.h"
Guido Casati's avatar
Guido Casati committed
44
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
45
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
46
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
47
#include "nr_unitary_defs.h"
48
#include "OCG_vars.h"
Thomas Laurent's avatar
Thomas Laurent committed
49
50
#include <openair2/LAYER2/MAC/mac_vars.h>
#include <openair2/RRC/LTE/rrc_vars.h>
knopp's avatar
knopp committed
51
#include <executables/softmodem-common.h>
52
#include <openair2/RRC/NR_UE/rrc_defs.h>
53
//#include "openair1/SIMULATION/NR_PHY/nr_dummy_functions.c"
Thomas Laurent's avatar
Thomas Laurent committed
54

55
56
#define NR_PRACH_DEBUG 1
#define PRACH_WRITE_OUTPUT_DEBUG 1
57

58
59
60
LCHAN_DESC DCCH_LCHAN_DESC,DTCH_DL_LCHAN_DESC,DTCH_UL_LCHAN_DESC;
rlc_info_t Rlc_info_um,Rlc_info_am_config;

61
62
63
PHY_VARS_gNB *gNB;
PHY_VARS_NR_UE *UE;
RAN_CONTEXT_t RC;
knopp's avatar
knopp committed
64
RU_t *ru;
65
66
67
double cpuf;
extern uint16_t prach_root_sequence_map0_3[838];
openair0_config_t openair0_cfg[MAX_CARDS];
68
//uint8_t nfapi_mode=0;
Roberto Louro Magueta's avatar
Roberto Louro Magueta committed
69
uint64_t downlink_frequency[MAX_NUM_CCs][4];
Thomas Laurent's avatar
Thomas Laurent committed
70
uint16_t sl_ahead = 0;
Thomas Laurent's avatar
Thomas Laurent committed
71
msc_interface_t msc_interface;
Roberto Louro Magueta's avatar
Roberto Louro Magueta committed
72
uint32_t N_RB_DL = 106;
73

74
//void dump_nr_prach_config(NR_DL_FRAME_PARMS *frame_parms,uint8_t subframe);
75

76
/* temporary dummy implem of get_softmodem_optmask, till basic simulators implemented as device */
Laurent Thomas's avatar
Laurent Thomas committed
77
msc_interface_t msc_interface;
78
79
uint64_t get_softmodem_optmask(void) {return 0;}
softmodem_params_t *get_softmodem_params(void) {return 0;}
80
81
82
83
int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0);  }
int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0);  }
int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0);  }
int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0);  }
84

85
86
87
88
89
90
91
92
93
94
void
rrc_data_ind(
  const protocol_ctxt_t *const ctxt_pP,
  const rb_id_t                Srb_id,
  const sdu_size_t             sdu_sizeP,
  const uint8_t   *const       buffer_pP
)
{
}

95
96
97
98
99
100
int ocp_gtpv1u_create_s1u_tunnel(instance_t instance,
                                 const gtpv1u_enb_create_tunnel_req_t  *create_tunnel_req,
                                 gtpv1u_enb_create_tunnel_resp_t *create_tunnel_resp) {
    return 0;
}

101
102
103
104
105
106
107
108
int
gtpv1u_create_s1u_tunnel(
  const instance_t                              instanceP,
  const gtpv1u_enb_create_tunnel_req_t *const  create_tunnel_req_pP,
  gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP
) {
  return 0;
}
109

110
111
112
113
114
115
116
117
int
rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(
  const protocol_ctxt_t *const ctxt_pP,
  const gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP,
  uint8_t                         *inde_list
) {
  return 0;
}
118

He Shanyun's avatar
He Shanyun committed
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
int
gtpv1u_create_ngu_tunnel(
  const instance_t instanceP,
  const gtpv1u_gnb_create_tunnel_req_t *  const create_tunnel_req_pP,
        gtpv1u_gnb_create_tunnel_resp_t * const create_tunnel_resp_pP){
  return 0;
}

int
gtpv1u_update_ngu_tunnel(
  const instance_t                              instanceP,
  const gtpv1u_gnb_create_tunnel_req_t *const  create_tunnel_req_pP,
  const rnti_t                                  prior_rnti
){
  return 0;
}

136
137
138
139
int ocp_gtpv1u_delete_s1u_tunnel(const instance_t instance, const gtpv1u_enb_delete_tunnel_req_t *const req_pP) {
  return 0;
}

He Shanyun's avatar
He Shanyun committed
140
141
142
143
144
145
146
147
148
int
nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(
  const protocol_ctxt_t *const ctxt_pP,
  const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP,
  uint8_t                         *inde_list
){
  return 0;
}

149
150
151
152
153
154
155
156
157
158
159
160
int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id,
                              const int CC_id,
                              const uint8_t gNB_index,
                              const frame_t frame,
                              const sub_frame_t sub_frame,
                              const rnti_t rnti,
                              const channel_t channel,
                              const uint8_t* pduP,
                              const sdu_size_t pdu_len)
{
  return 0;
}
161

162
163
164
165
166
void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index)
{
  return;
}

167
168
169
170
171
172
int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP,
                              const int         CC_id,
                              const uint8_t     gNB_id,
                              const frame_t     frameP,
                              const rb_id_t     Srb_id,
                              uint8_t           *buffer_pP)
173
174
175
176
{
  return 0;
}

177
178
179
// Dummy function to avoid linking error at compilation of nr-prachsim
int is_x2ap_enabled(void)
{
Roberto Louro Magueta's avatar
Roberto Louro Magueta committed
180
181
182
  return 0;
}

183
184
185
186
187
188
int nr_derive_key(int alg_type, uint8_t alg_id,
               const uint8_t key[32], uint8_t **out)
{
  return 0;
}

Roberto Louro Magueta's avatar
Roberto Louro Magueta committed
189
190
191
192
193
194
195
196
197
198
199
int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(module_id_t     module_idP,
                                            int             CC_idP,
                                            int             UE_id,
                                            rnti_t          rntiP,
                                            const uint8_t   *sduP,
                                            sdu_size_t      sdu_lenP,
                                            const uint8_t   *sdu2P,
                                            sdu_size_t      sdu2_lenP) {
  return 0;
}

Sakthivel Velumani's avatar
Sakthivel Velumani committed
200
201
202
typedef struct {
  uint64_t       optmask;   //mask to store boolean config options
  uint8_t        nr_dlsch_parallel; // number of threads for dlsch decoding, 0 means no parallelization
203
  tpool_t        Tpool;             // thread pool
Sakthivel Velumani's avatar
Sakthivel Velumani committed
204
205
206
207
208
209
210
211
} nrUE_params_t;

nrUE_params_t nrUE_params;

nrUE_params_t *get_nrUE_params(void) {
  return &nrUE_params;
}

Sakthivel Velumani's avatar
Sakthivel Velumani committed
212
213
void processSlotTX(void *arg) {}

214
int main(int argc, char **argv){
215
216
217

  char c;

218
  double sigma2, sigma2_dB = 0, SNR, snr0 = -2.0, snr1 = 0.0, ue_speed0 = 0.0, ue_speed1 = 0.0;
219
  double **s_re, **s_im, **r_re, **r_im, iqim = 0.0, delay_avg = 0, ue_speed = 0, fs=-1, bw;
220
  int i, l, aa, aarx, **txdata, trial, n_frames = 1, prach_start, rx_prach_start; //, ntrials=1;
221
  int N_RB_UL = 106, delay = 0, NCS_config = 13, rootSequenceIndex = 1, threequarter_fs = 0, mu = 1, fd_occasion = 0, loglvl = OAILOG_INFO, numRA = 0, prachStartSymbol = 0;
222
  uint8_t snr1set = 0, ue_speed1set = 0, transmission_mode = 1, n_tx = 1, n_rx = 1, awgn_flag = 0, msg1_frequencystart = 0, num_prach_fd_occasions = 1, prach_format=0;
223
  uint8_t frame = 1, slot=19, slot_gNB=19, config_index = 98, prach_sequence_length = 1, restrictedSetConfig = 0, N_dur, N_t_slot, start_symbol;
224
  uint16_t Nid_cell = 0, preamble_tx = 0, preamble_delay, format, format0, format1;
Thomas Schlichter's avatar
Thomas Schlichter committed
225
  uint32_t tx_lev = 10000, prach_errors = 0; //,tx_lev_dB;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
226
  uint64_t SSB_positions = 0x01;
227
228
229
230
  uint16_t RA_sfn_index;
  uint8_t N_RA_slot;
  uint8_t config_period;
  int prachOccasion = 0;
Francesco Mani's avatar
Francesco Mani committed
231
  double DS_TDL = .03;
Thomas Laurent's avatar
Thomas Laurent committed
232
  NB_UE_INST=1;
233
234
235
236

  //  int8_t interf1=-19,interf2=-19;
  //  uint8_t abstraction_flag=0,calibration_flag=0;
  //  double prach_sinr;
237
238
  //  uint32_t nsymb;
  //  uint16_t preamble_max, preamble_energy_max;
239
240
241
  FILE *input_fd=NULL;
  char* input_file=NULL;
  int n_bytes=0;
242

243
  NR_DL_FRAME_PARMS *frame_parms;
244
  NR_PRACH_RESOURCES_t prach_resources;
245
246
247
248
  nfapi_nr_prach_config_t *prach_config;
  nfapi_nr_prach_pdu_t *prach_pdu;
  fapi_nr_prach_config_t *ue_prach_config;
  fapi_nr_ul_config_prach_pdu *ue_prach_pdu;
249

250
251
  channel_desc_t *UE2gNB;
  SCM_t channel_model = Rayleigh1;
252
253
  cpuf = get_cpu_freq_GHz();

knopp's avatar
knopp committed
254
  if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == 0) {
255
256
257
258
259
    exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
  }

  randominit(0);

260
  while ((c = getopt (argc, argv, "hHaA:Cc:l:r:p:g:m:n:s:S:t:x:y:v:V:z:N:F:d:Z:L:R:E")) != -1) {
261
262
263
264
265
266
267
268
    switch (c) {
    case 'a':
      printf("Running AWGN simulation\n");
      awgn_flag = 1;
      /* ntrials not used later, no need to set */
      //ntrials=1;
      break;

269
270
271
272
    case 'c':
      config_index = atoi(optarg);
      break;

273
274
275
276
    case 'l':
      loglvl = atoi(optarg);
      break;

277
278
279
280
    case 'r':
      msg1_frequencystart = atoi(optarg);
      break;

281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
    case 'd':
      delay = atoi(optarg);
      break;

    case 'g':
      switch((char)*optarg) {
      case 'A':
        channel_model=SCM_A;
        break;

      case 'B':
        channel_model=SCM_B;
        break;

      case 'C':
        channel_model=SCM_C;
        break;

      case 'D':
        channel_model=SCM_D;
        break;

      case 'E':
        channel_model=EPA;
        break;

      case 'F':
        channel_model=EVA;
        break;

      case 'G':
        channel_model=ETU;
        break;

      case 'H':
        channel_model=Rayleigh8;
317
        break;
318
319
320

      case 'I':
        channel_model=Rayleigh1;
321
        break;
322
323
324

      case 'J':
        channel_model=Rayleigh1_corr;
325
        break;
326
327
328

      case 'K':
        channel_model=Rayleigh1_anticorr;
329
        break;
330
331
332

      case 'L':
        channel_model=Rice8;
333
        break;
334
335
336

      case 'M':
        channel_model=Rice1;
337
        break;
338
339
340
341
342
343

      case 'N':
        channel_model=Rayleigh1_800;
        break;

      default:
344
        printf("Unsupported channel model!\n");
345
346
347
348
349
350
351
352
353
        exit(-1);
      }

      break;

    case 'E':
      threequarter_fs=1;
      break;

354
355
356
357
    case 'm':
      mu = atoi(optarg);
      break;

358
359
360
361
362
363
    case 'n':
      n_frames = atoi(optarg);
      break;

    case 's':
      snr0 = atof(optarg);
364
      printf("Setting SNR0 to %f\n",snr0);
365
366
367
368
369
      break;

    case 'S':
      snr1 = atof(optarg);
      snr1set=1;
370
      printf("Setting SNR1 to %f\n",snr1);
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
      break;

    case 'p':
      preamble_tx=atoi(optarg);
      break;

    case 'v':
      ue_speed0 = atoi(optarg);
      break;

    case 'V':
      ue_speed1 = atoi(optarg);
      ue_speed1set = 1;
      break;

    case 'Z':
      NCS_config = atoi(optarg);

      if ((NCS_config > 15) || (NCS_config < 0))
        printf("Illegal NCS_config %d, (should be 0-15)\n",NCS_config);

      break;

    case 'H':
      printf("High-Speed Flag enabled\n");
396
      restrictedSetConfig = 1;
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
      break;

    case 'L':
      rootSequenceIndex = atoi(optarg);

      if ((rootSequenceIndex < 0) || (rootSequenceIndex > 837))
        printf("Illegal rootSequenceNumber %d, (should be 0-837)\n",rootSequenceIndex);

      break;

    case 'x':
      transmission_mode=atoi(optarg);

      if ((transmission_mode!=1) &&
          (transmission_mode!=2) &&
          (transmission_mode!=6)) {
413
        printf("Unsupported transmission mode %d\n",transmission_mode);
414
415
416
417
418
419
420
421
422
        exit(-1);
      }

      break;

    case 'y':
      n_tx=atoi(optarg);

      if ((n_tx==0) || (n_tx>2)) {
423
        printf("Unsupported number of tx antennas %d\n",n_tx);
424
425
426
427
428
429
430
431
432
        exit(-1);
      }

      break;

    case 'z':
      n_rx=atoi(optarg);

      if ((n_rx==0) || (n_rx>2)) {
433
        printf("Unsupported number of rx antennas %d\n",n_rx);
434
435
436
437
438
439
440
441
442
443
444
445
446
447
        exit(-1);
      }

      break;

    case 'N':
      Nid_cell = atoi(optarg);
      break;

    case 'R':
      N_RB_UL = atoi(optarg);
      break;

    case 'F':
448
449
450
451
452
453
454
455
      input_fd = fopen(optarg,"r");
      input_file = optarg;
      
      if (input_fd==NULL) {
	printf("Problem with filename %s\n",optarg);
	exit(-1);
      }
      
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
481
482
483
484
      break;

    default:
    case 'h':
      printf("%s -h(elp) -a(wgn on) -p(extended_prefix) -N cell_id -f output_filename -F input_filename -g channel_model -n n_frames -s snr0 -S snr1 -x transmission_mode -y TXant -z RXant -i Intefrence0 -j Interference1 -A interpolation_file -C(alibration offset dB) -N CellId\n",
             argv[0]);
      printf("-h This message\n");
      printf("-a Use AWGN channel and not multipath\n");
      printf("-n Number of frames to simulate\n");
      printf("-s Starting SNR, runs from SNR0 to SNR0 + 5 dB.  If n_frames is 1 then just SNR is simulated\n");
      printf("-S Ending SNR, runs from SNR0 to SNR1\n");
      printf("-g [A,B,C,D,E,F,G,I,N] Use 3GPP SCM (A,B,C,D) or 36-101 (E-EPA,F-EVA,G-ETU) or Rayleigh1 (I) or Rayleigh1_800 (N) models (ignores delay spread and Ricean factor)\n");
      printf("-z Number of RX antennas used in gNB\n");
      printf("-N Nid_cell\n");
      printf("-O oversampling factor (1,2,4,8,16)\n");
      //    printf("-f PRACH format (0=1,1=2,2=3,3=4)\n");
      printf("-d Channel delay \n");
      printf("-v Starting UE velocity in km/h, runs from 'v' to 'v+50km/h'. If n_frames is 1 just 'v' is simulated \n");
      printf("-V Ending UE velocity in km/h, runs from 'v' to 'V'");
      printf("-L rootSequenceIndex (0-837)\n");
      printf("-Z NCS_config (ZeroCorrelationZone) (0-15)\n");
      printf("-H Run with High-Speed Flag enabled \n");
      printf("-R Number of PRB (6,15,25,50,75,100)\n");
      printf("-F Input filename (.txt format) for RX conformance testing\n");
      exit (-1);
      break;
    }
  }

485
  // Configure log
486
487
488
489
490
  logInit();
  set_glog(loglvl);
  T_stdout = 1;
  SET_LOG_DEBUG(PRACH); 

491
  // Configure gNB and RU
492
493
494
  RC.gNB = (PHY_VARS_gNB**) malloc(2*sizeof(PHY_VARS_gNB *));
  RC.gNB[0] = malloc(sizeof(PHY_VARS_gNB));
  memset(RC.gNB[0],0,sizeof(PHY_VARS_gNB));
495
496
497
498
499
500

  RC.ru = (RU_t**) malloc(2*sizeof(RU_t *));
  RC.ru[0] = (RU_t*) malloc(sizeof(RU_t ));
  memset(RC.ru[0],0,sizeof(RU_t));
  RC.nb_RU = 1;

501
502
503
504
505
506
  gNB          = RC.gNB[0];
  ru           = RC.ru[0];
  frame_parms  = &gNB->frame_parms;
  prach_config = &gNB->gNB_config.prach_config;
  prach_pdu    = &gNB->prach_vars.list[0].pdu;
  frame_parms  = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH)
507
508
509
510
511
512

  s_re = malloc(2*sizeof(double*));
  s_im = malloc(2*sizeof(double*));
  r_re = malloc(2*sizeof(double*));
  r_im = malloc(2*sizeof(double*));

513
514
515
516
517
518
  frame_parms->nb_antennas_tx   = n_tx;
  frame_parms->nb_antennas_rx   = n_rx;
  frame_parms->N_RB_DL          = N_RB_UL;
  frame_parms->N_RB_UL          = N_RB_UL;
  frame_parms->threequarter_fs  = threequarter_fs;
  frame_parms->frame_type       = TDD;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
519
  frame_parms->freq_range       = (mu==1 ? nr_FR1 : nr_FR2);
520
521
522
523
  frame_parms->numerology_index = mu;

  nr_phy_config_request_sim(gNB, N_RB_UL, N_RB_UL, mu, Nid_cell, SSB_positions);

524
  uint64_t absoluteFrequencyPointA = to_nrarfcn(frame_parms->nr_band,
525
526
527
528
				       frame_parms->dl_CarrierFreq,
				       frame_parms->numerology_index,
				       frame_parms->N_RB_UL*(180e3)*(1 << frame_parms->numerology_index));

Florian Kaltenberger's avatar
Florian Kaltenberger committed
529
  uint8_t subframe = slot/frame_parms->slots_per_subframe;
530
531
532
533
534
535
  
  if (config_index<67 && mu==1)  { prach_sequence_length=0; slot = subframe*2; slot_gNB = 1+(subframe*2); }
  uint16_t N_ZC = prach_sequence_length == 0 ? 839 : 139;

  printf("Config_index %d, prach_sequence_length %d\n",config_index,prach_sequence_length);

536
537
538
539
540
541
542
543
544
545
546
547

  printf("FFT Size %d, Extended Prefix %d, Samples per subframe %d, Frame type %s, Frequency Range %s\n",
         NUMBER_OF_OFDM_CARRIERS,
         frame_parms->Ncp,
         frame_parms->samples_per_subframe,
         frame_parms->frame_type == FDD ? "FDD" : "TDD",
         frame_parms->freq_range == nr_FR1 ? "FR1" : "FR2");

  ru->nr_frame_parms = frame_parms;
  ru->if_south       = LOCAL_RF;
  ru->nb_tx          = n_tx;
  ru->nb_rx          = n_rx;
knopp's avatar
knopp committed
548
549
  ru->num_gNB        = 1;
  ru->gNB_list[0]    = gNB;
550
551
  gNB->gNB_config.carrier_config.num_tx_ant.value = 1;
  gNB->gNB_config.carrier_config.num_rx_ant.value = 1;
552
553
554
555
556
557
558
559
  if (mu==1)
    gNB->gNB_config.tdd_table.tdd_period.value = 6;
  else if (mu==3)
    gNB->gNB_config.tdd_table.tdd_period.value = 3;
  else {
    printf("unsupported numerology %d\n",mu);
    exit(-1);
  }
560
561
562
563

  gNB->gNB_config.prach_config.num_prach_fd_occasions.value = num_prach_fd_occasions;
  gNB->gNB_config.prach_config.num_prach_fd_occasions_list = (nfapi_nr_num_prach_fd_occasions_t *) malloc(num_prach_fd_occasions*sizeof(nfapi_nr_num_prach_fd_occasions_t));

564
  gNB->proc.slot_rx       = slot;
565

knopp's avatar
knopp committed
566
  int ret = get_nr_prach_info_from_index(config_index,
567
568
569
570
571
572
573
574
575
576
577
578
					 (int)frame,
					 (int)slot_gNB,
					 absoluteFrequencyPointA,
					 mu,
					 frame_parms->frame_type,
					 &format,
					 &start_symbol,
					 &N_t_slot,
					 &N_dur,
					 &RA_sfn_index,
					 &N_RA_slot,
					 &config_period);
579

knopp's avatar
knopp committed
580
  if (ret == 0) {printf("No prach in %d.%d, mu %d, config_index %d\n",frame,slot,mu,config_index); exit(-1);}
581
582
583
584
585
  format0 = format&0xff;      // first column of format from table
  format1 = (format>>8)&0xff; // second column of format from table

  if (format1 != 0xff) {
    switch(format0) {
586
    case 0xa1:
587
      prach_format = 11;
588
589
      break;
    case 0xa2:
590
      prach_format = 12;
591
592
      break;
    case 0xa3:
593
      prach_format = 13;
594
      break;
595
596
597
598
    default:
      AssertFatal(1==0, "Only formats A1/B1 A2/B2 A3/B3 are valid for dual format");
    }
  } else {
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
    switch(format0) { // single PRACH format
    case 0:
      prach_format = 0;
      break;
    case 1:
      prach_format = 1;
      break;
    case 2:
      prach_format = 2;
      break;
    case 3:
      prach_format = 3;
      break;
    case 0xa1:
      prach_format = 4;
      break;
    case 0xa2:
      prach_format = 5;
      break;
    case 0xa3:
      prach_format = 6;
      break;
    case 0xb1:
      prach_format = 7;
      break;
    case 0xb4:
      prach_format = 8;
      break;
    case 0xc0:
      prach_format = 9;
      break;
    case 0xc2:
      prach_format = 10;
      break;
633
    default:
634
      AssertFatal(1 == 0, "Invalid PRACH format");
635
636
    }
  }
637

638
639
  printf("PRACH format %d\n",prach_format);
      
640
641
642
643
644
  prach_config->num_prach_fd_occasions_list[fd_occasion].prach_root_sequence_index.value = rootSequenceIndex;
  prach_config->num_prach_fd_occasions_list[fd_occasion].k1.value                        = msg1_frequencystart;
  prach_config->restricted_set_config.value                                              = restrictedSetConfig;
  prach_config->prach_sequence_length.value                                              = prach_sequence_length;
  prach_pdu->num_cs                                                                      = get_NCS(NCS_config, format0, restrictedSetConfig);
645
  prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value        = 1+(64/(N_ZC/prach_pdu->num_cs));
646
  prach_pdu->prach_format                                                                = prach_format;
647
648

  memcpy((void*)&ru->config,(void*)&RC.gNB[0]->gNB_config,sizeof(ru->config));
649
  RC.nb_nr_L1_inst=1;
650
  phy_init_nr_gNB(gNB,0,1); //lowmem
651
  nr_phy_init_RU(ru);
652
653
  gNB->common_vars.rxdata = ru->common.rxdata;
  set_tdd_config_nr(&gNB->gNB_config, mu, 7, 6, 2, 4);
654

655
  // Configure UE
656
657
658
659
660
661
  UE = malloc(sizeof(PHY_VARS_NR_UE));
  memset((void*)UE,0,sizeof(PHY_VARS_NR_UE));
  PHY_vars_UE_g = malloc(2*sizeof(PHY_VARS_NR_UE**));
  PHY_vars_UE_g[0] = malloc(2*sizeof(PHY_VARS_NR_UE*));
  PHY_vars_UE_g[0][0] = UE;
  memcpy(&UE->frame_parms,frame_parms,sizeof(NR_DL_FRAME_PARMS));
662
663
664
  UE->nrUE_config.prach_config.num_prach_fd_occasions_list = (fapi_nr_num_prach_fd_occasions_t *) malloc(num_prach_fd_occasions*sizeof(fapi_nr_num_prach_fd_occasions_t));

  if (init_nr_ue_signal(UE, 1, 0) != 0){
665
666
667
668
    printf("Error at UE NR initialisation\n");
    exit(-1);
  }

669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
  ue_prach_pdu           = &UE->prach_vars[0]->prach_pdu;
  ue_prach_config        = &UE->nrUE_config.prach_config;
  UE->prach_resources[0] = &prach_resources;
  txdata                 = UE->common_vars.txdata;

  UE->prach_vars[0]->amp        = AMP;
  ue_prach_pdu->root_seq_id     = rootSequenceIndex;
  ue_prach_pdu->num_cs          = get_NCS(NCS_config, format0, restrictedSetConfig);
  ue_prach_pdu->restricted_set  = restrictedSetConfig;
  ue_prach_pdu->freq_msg1       = msg1_frequencystart;
  ue_prach_pdu->prach_format    = prach_format;

  ue_prach_config->prach_sub_c_spacing                                                = mu;
  ue_prach_config->prach_sequence_length                                              = prach_sequence_length;
  ue_prach_config->restricted_set_config                                              = restrictedSetConfig;
684
  ue_prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences        = prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value ;
685
686
687
688
689
690
691
692
693
694
  ue_prach_config->num_prach_fd_occasions_list[fd_occasion].prach_root_sequence_index = rootSequenceIndex;
  ue_prach_config->num_prach_fd_occasions_list[fd_occasion].k1                        = msg1_frequencystart;

  if (preamble_tx == 99)
    preamble_tx = (uint16_t)(taus()&0x3f);

  if (n_frames == 1)
    printf("raPreamble %d\n",preamble_tx);

  UE->prach_resources[0]->ra_PreambleIndex = preamble_tx;
695
  UE->prach_resources[0]->init_msg1 = 1;
696

697
698
699
  // Configure channel
  bw = N_RB_UL*(180e3)*(1 << frame_parms->numerology_index);
  AssertFatal(bw<=122.88e6,"Illegal channel bandwidth %f (mu %d,N_RB_UL %d)\n", bw, frame_parms->numerology_index, N_RB_UL);
700

701
702
703
704
705
706
  if (bw <= 30.72e6)
    fs = 30.72e6;
  else if (bw <= 61.44e6)
    fs = 61.44e6;
  else if (bw <= 122.88e6)
    fs = 122.88e6;
707
708
709
710
711
712

  LOG_I(PHY,"Running with bandwidth %f Hz, fs %f samp/s, FRAME_LENGTH_COMPLEX_SAMPLES %d\n",bw,fs,FRAME_LENGTH_COMPLEX_SAMPLES);

  UE2gNB = new_channel_desc_scm(UE->frame_parms.nb_antennas_tx,
                                gNB->frame_parms.nb_antennas_rx,
                                channel_model,
713
714
                                fs,
                                bw,
Francesco Mani's avatar
Francesco Mani committed
715
                                DS_TDL,
716
717
                                0.0,
                                delay,
718
                                0, 0);
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737

  if (UE2gNB==NULL) {
    printf("Problem generating channel model. Exiting.\n");
    exit(-1);
  }

  for (i=0; i<2; i++) {

    s_re[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double));
    bzero(s_re[i],FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double));
    s_im[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double));
    bzero(s_im[i],FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double));

    r_re[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double));
    bzero(r_re[i],FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double));
    r_im[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double));
    bzero(r_im[i],FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double));
  }

738
739
740
741
742
  // compute PRACH sequence
  compute_nr_prach_seq(prach_config->prach_sequence_length.value,
                       prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value,
                       prach_config->num_prach_fd_occasions_list[fd_occasion].prach_root_sequence_index.value,
                       gNB->X_u);
743

744
745
746
747
  compute_nr_prach_seq(ue_prach_config->prach_sequence_length,
                       ue_prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences,
                       ue_prach_config->num_prach_fd_occasions_list[fd_occasion].prach_root_sequence_index,
                       UE->X_u);
748

749
  /*tx_lev = generate_nr_prach(UE,
750
			     0, //gNB_id,
Guido Casati's avatar
Guido Casati committed
751
			     subframe); */ //commented for testing purpose
752

753
  UE_nr_rxtx_proc_t proc={0};
754
755
  proc.frame_tx   = frame;
  proc.nr_slot_tx = slot;
Guido Casati's avatar
Guido Casati committed
756
  nr_ue_prach_procedures(UE, &proc, 0);
757
758
759
760

  /* tx_lev_dB not used later, no need to set */
  //tx_lev_dB = (unsigned int) dB_fixed(tx_lev);

761
  prach_start = subframe*frame_parms->samples_per_subframe;
762
763

  #ifdef NR_PRACH_DEBUG
764
  LOG_M("txsig0.m", "txs0", &txdata[0][subframe*frame_parms->samples_per_subframe], frame_parms->samples_per_subframe, 1, 1);
765
    LOG_M("txsig0_frame.m","txs0", txdata[0],frame_parms->samples_per_frame,1,1);
766
  #endif
767
768

  // multipath channel
769
  // dump_nr_prach_config(&gNB->frame_parms,subframe);
770

771
  for (i = 0; i < frame_parms->samples_per_subframe<<1; i++) {
772
773
    for (aa=0; aa<1; aa++) {
      if (awgn_flag == 0) {
774
775
        s_re[aa][i] = ((double)(((short *)&txdata[aa][prach_start]))[(i<<1)]);
        s_im[aa][i] = ((double)(((short *)&txdata[aa][prach_start]))[(i<<1)+1]);
776
777
778
      } else {
        for (aarx=0; aarx<gNB->frame_parms.nb_antennas_rx; aarx++) {
          if (aa==0) {
779
780
            r_re[aarx][i] = ((double)(((short *)&txdata[aa][prach_start]))[(i<<1)]);
            r_im[aarx][i] = ((double)(((short *)&txdata[aa][prach_start]))[(i<<1)+1]);
781
          } else {
782
783
            r_re[aarx][i] += ((double)(((short *)&txdata[aa][prach_start]))[(i<<1)]);
            r_im[aarx][i] += ((double)(((short *)&txdata[aa][prach_start]))[(i<<1)+1]);
784
785
786
787
788
789
          }
        }
      }
    }
  }

790
791
792
793
794
795
796
797
  if (snr1set == 0) {
    if (n_frames == 1)
      snr1 = snr0 + .1;
    else
      snr1 = snr0 + 5.0;
  }

  printf("SNR0 %f, SNR1 %f\n", snr0, snr1);
798

799
800
801
802
803
804
805
  if (ue_speed1set == 0) {
    if (n_frames == 1)
      ue_speed1 = ue_speed0 + 10;
    else
      ue_speed1 = ue_speed0 + 50;
  }

806
  rx_prach_start = subframe*frame_parms->samples_per_subframe;
807
  if (n_frames==1) printf("slot %d, rx_prach_start %d\n",slot,rx_prach_start);
808
809
  uint16_t preamble_rx, preamble_energy;

810

Thomas Schlichter's avatar
Thomas Schlichter committed
811
  for (SNR=snr0; SNR<snr1; SNR+=.1) {
812
813
814
815
816
817
818
819
820
    for (ue_speed=ue_speed0; ue_speed<ue_speed1; ue_speed+=10) {
      delay_avg = 0.0;
      // max Doppler shift
      UE2gNB->max_Doppler = 1.9076e9*(ue_speed/3.6)/3e8;
      printf("n_frames %d SNR %f\n",n_frames,SNR);
      prach_errors=0;

      for (trial=0; trial<n_frames; trial++) {

821
	if (input_fd==NULL) {
822
        sigma2_dB = 10*log10((double)tx_lev) - SNR - 10*log10(N_RB_UL*12/N_ZC);
823
824
825
826
827
828
829
830
831

        if (n_frames==1)
          printf("sigma2_dB %f (SNR %f dB) tx_lev_dB %f\n",sigma2_dB,SNR,10*log10((double)tx_lev));

        //AWGN
        sigma2 = pow(10,sigma2_dB/10);
        //  printf("Sigma2 %f (sigma2_dB %f)\n",sigma2,sigma2_dB);

        if (awgn_flag == 0) {
832
          multipath_tv_channel(UE2gNB, s_re, s_im, r_re, r_im, frame_parms->samples_per_frame, 0);
833
834
835
836
837
838
839
840
        }

        if (n_frames==1) {
          printf("rx_level data symbol %f, tx_lev %f\n",
                 10*log10(signal_energy_fp(r_re,r_im,1,OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES,0)),
                 10*log10(tx_lev));
        }

841
        for (i = 0; i< frame_parms->samples_per_subframe; i++) {
842
          for (aa = 0; aa < frame_parms->nb_antennas_rx; aa++) {
843
844
            ((short*) &ru->common.rxdata[aa][rx_prach_start])[2*i] = (short) (.167*(r_re[aa][i] +sqrt(sigma2/2)*gaussdouble(0.0,1.0)));
            ((short*) &ru->common.rxdata[aa][rx_prach_start])[2*i+1] = (short) (.167*(r_im[aa][i] + (iqim*r_re[aa][i]) + sqrt(sigma2/2)*gaussdouble(0.0,1.0)));
845
846
          }
        }
847
	} else {
848
	  n_bytes = fread(&ru->common.rxdata[0][rx_prach_start],sizeof(int32_t),frame_parms->samples_per_subframe,input_fd);
849
	  printf("fread %d bytes from file %s\n",n_bytes,input_file);
850
851
	  if (n_bytes!=frame_parms->samples_per_subframe) {
	    printf("expected %d bytes\n",frame_parms->samples_per_subframe);
852
853
854
855
	    exit(-1);
	  }
	}

856
857
858
859
860
861
862
	for (l = 0; l < frame_parms->symbols_per_slot; l++) {
	  for (aa = 0; aa < frame_parms->nb_antennas_rx; aa++) {
	    nr_slot_fep_ul(frame_parms,
			   ru->common.rxdata[aa],
			   ru->common.rxdataF[aa],
			   l,
			   slot,
863
			   ru->N_TA_offset);
864
865
866
	  }
	}
	
867
        rx_nr_prach_ru(ru, prach_format, numRA, prachStartSymbol, prachOccasion, frame, slot);
868

869
        gNB->prach_vars.rxsigF = ru->prach_rxsigF[prachOccasion];
870
	if (n_frames == 1) printf("ncs %d,num_seq %d\n",prach_pdu->num_cs,  prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value);
871
        rx_nr_prach(gNB, prach_pdu, prachOccasion, frame, subframe, &preamble_rx, &preamble_energy, &preamble_delay);
872

873
	//        printf(" preamble_energy %d preamble_rx %d preamble_tx %d \n", preamble_energy, preamble_rx, preamble_tx);
874
875

        if (preamble_rx != preamble_tx)
876
          prach_errors++;
877
        else
878
          delay_avg += (double)preamble_delay;
879
880

        N_ZC = (prach_sequence_length) ? 139 : 839;
881
882

        if (n_frames==1) {
883
884
          printf("preamble %d (tx %d) : energy %d, delay %d\n",preamble_rx,preamble_tx,preamble_energy,preamble_delay);
          #ifdef NR_PRACH_DEBUG
885
	  LOG_M("prach0.m","prach0", &txdata[0][prach_start], frame_parms->samples_per_subframe, 1, 1);
886
            LOG_M("prachF0.m","prachF0", &gNB->prach_vars.prachF[0], N_ZC, 1, 1);
887
888
            LOG_M("rxsig0.m","rxs0", &gNB->common_vars.rxdata[0][subframe*frame_parms->samples_per_subframe], frame_parms->samples_per_subframe, 1, 1);
            LOG_M("ru_rxsig0.m","rxs0", &ru->common.rxdata[0][subframe*frame_parms->samples_per_subframe], frame_parms->samples_per_subframe, 1, 1);
889
890
            LOG_M("ru_rxsigF0.m","rxsF0", ru->common.rxdataF[0], frame_parms->ofdm_symbol_size*frame_parms->symbols_per_slot, 1, 1);
            LOG_M("ru_prach_rxsigF0.m","rxsF0", ru->prach_rxsigF[0][0], N_ZC, 1, 1);
891
892
893
            LOG_M("prach_preamble.m","prachp", &gNB->X_u[0], N_ZC, 1, 1);
            LOG_M("ue_prach_preamble.m","prachp", &UE->X_u[0], N_ZC, 1, 1);
          #endif
894
895
896
        }
      }

897
      printf("SNR %f dB, UE Speed %f km/h: errors %d/%d (delay %f)\n", SNR, ue_speed, prach_errors, n_frames, delay_avg/(double)(n_frames-prach_errors));
898
899
      if (input_fd)
	break;
Thomas Schlichter's avatar
Thomas Schlichter committed
900
901
      if (prach_errors)
        break;
902
903

    } // UE Speed loop
Thomas Schlichter's avatar
Thomas Schlichter committed
904
905
906
907
    if (!prach_errors) {
      printf("PRACH test OK\n");
      break;
    }
908
909
    if (input_fd)
      break;
910
911
912
913
914
915
916
917
918
919
920
921
922
923
  } //SNR loop

  for (i=0; i<2; i++) {
    free(s_re[i]);
    free(s_im[i]);
    free(r_re[i]);
    free(r_im[i]);
  }

  free(s_re);
  free(s_im);
  free(r_re);
  free(r_im);

924
925
  if (input_fd) fclose(input_fd);

926
927
  return(0);
}