pbchsim.c 19 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 25 26 27
/*
 * 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>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
28 29 30
#include "common/config/config_userapi.h"
#include "common/utils/LOG/log.h"
#include "common/ran_context.h" 
31 32 33 34
#include "PHY/types.h"
#include "PHY/defs_nr_common.h"
#include "PHY/defs_nr_UE.h"
#include "PHY/defs_gNB.h"
35
#include "PHY/NR_REFSIG/refsig_defs_ue.h"
36
#include "PHY/NR_REFSIG/nr_mod_table.h"
37 38
#include "PHY/MODULATION/modulation_eNB.h"
#include "PHY/MODULATION/modulation_UE.h"
39
#include "PHY/INIT/phy_init.h"
40 41
#include "PHY/NR_TRANSPORT/nr_transport.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
42
#include "PHY/NR_UE_ESTIMATION/nr_estimation.h"
43
#include "PHY/phy_vars.h"
44
#include "SCHED_NR/sched_nr.h"
45 46 47 48
#include "openair1/SIMULATION/TOOLS/sim.h"
#include "openair1/SIMULATION/RF/rf.h"
#include "openair1/SIMULATION/NR_PHY/nr_unitary_defs.h"
#include "openair1/SIMULATION/NR_PHY/nr_dummy_functions.c"
49

50
//#define DEBUG_NR_PBCHSIM
51 52 53 54

PHY_VARS_gNB *gNB;
PHY_VARS_NR_UE *UE;
RAN_CONTEXT_t RC;
55 56
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];

57 58
double cpuf;
int nfapi_mode=0;
59

60

yilmazt's avatar
yilmazt committed
61
uint16_t NB_UE_INST = 1;
62

63
// needed for some functions
64
openair0_config_t openair0_cfg[MAX_CARDS];
65

66 67 68
int main(int argc, char **argv)
{
  char c;
yilmazt's avatar
yilmazt committed
69
  int i,aa;//,l;
70
  double sigma2, sigma2_dB=10,SNR,snr0=-2.0,snr1=2.0;
Francesco Mani's avatar
Francesco Mani committed
71
  double cfo=0;
72
  uint8_t snr1set=0;
73 74
  int **txdata;
  double **s_re,**s_im,**r_re,**r_im;
75
  //double iqim = 0.0;
Francesco Mani's avatar
Francesco Mani committed
76
  double ip =0.0;
77
  //unsigned char pbch_pdu[6];
78 79 80
  //  int sync_pos, sync_pos_slot;
  //  FILE *rx_frame_file;
  FILE *output_fd = NULL;
81
  //uint8_t write_output_file=0;
82
  //int result;
yilmazt's avatar
yilmazt committed
83
  //int freq_offset;
84 85
  //  int subframe_offset;
  //  char fname[40], vname[40];
yilmazt's avatar
yilmazt committed
86
  int trial,n_trials=1,n_errors=0,n_errors_payload=0;
87 88
  uint8_t transmission_mode = 1,n_tx=1,n_rx=1;
  uint16_t Nid_cell=0;
89
  uint64_t SSB_positions=0x01;
90 91

  channel_desc_t *gNB2UE;
yilmazt's avatar
yilmazt committed
92

93 94
  //uint8_t extended_prefix_flag=0;
  //int8_t interf1=-21,interf2=-21;
95 96

  FILE *input_fd=NULL,*pbch_file_fd=NULL;
97

yilmazt's avatar
yilmazt committed
98 99 100 101 102
  //uint32_t nsymb,tx_lev,tx_lev1 = 0,tx_lev2 = 0;
  //char input_val_str[50],input_val_str2[50];
  //uint8_t frame_mod4,num_pdcch_symbols = 0;
  //double pbch_sinr;
  //int pbch_tx_ant;
103 104 105

  SCM_t channel_model=AWGN;//Rayleigh1_anticorr;

yilmazt's avatar
yilmazt committed
106

107
  int N_RB_DL=273,mu=1;
108

109
  //unsigned char frame_type = 0;
110 111
  unsigned char pbch_phase = 0;

112
  int frame=0;
113 114 115
  int frame_length_complex_samples;
  int frame_length_complex_samples_no_prefix;
  NR_DL_FRAME_PARMS *frame_parms;
116

Guy De Souza's avatar
Guy De Souza committed
117
  int ret, payload_ret=0;
118 119
  int run_initial_sync=0;

120 121
  int loglvl=OAILOG_WARNING;

122 123
  float target_error_rate = 0.01;

124 125
  cpuf = get_cpu_freq_GHz();

126
  if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == 0) {
yilmazt's avatar
yilmazt committed
127
    exit_fun("[NR_PBCHSIM] Error, configuration module init failed\n");
128 129
  }

130
  randominit(0);
131

132
  while ((c = getopt (argc, argv, "f:hA:pf:g:i:j:n:o:s:S:t:x:y:z:M:N:F:GR:dP:IL:")) != -1) {
133
    switch (c) {
134
    /*case 'f':
135 136 137 138 139 140 141 142
      write_output_file=1;
      output_fd = fopen(optarg,"w");

      if (output_fd==NULL) {
        printf("Error opening %s\n",optarg);
        exit(-1);
      }

143
      break;*/
144

145
    /*case 'd':
146
      frame_type = 1;
147
      break;*/
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179

    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;

      default:
180
        printf("Unsupported channel model! Exiting.\n");
181 182 183 184 185
        exit(-1);
      }

      break;

186
    /*case 'i':
187 188 189 190 191
      interf1=atoi(optarg);
      break;

    case 'j':
      interf2=atoi(optarg);
192
      break;*/
193 194

    case 'n':
195
      n_trials = atoi(optarg);
196 197
      break;

Francesco Mani's avatar
Francesco Mani committed
198 199
    case 'o':
      cfo = atof(optarg);
200 201 202
#ifdef DEBUG_NR_PBCHSIM
      printf("Setting CFO to %f Hz\n",cfo);
#endif
Francesco Mani's avatar
Francesco Mani committed
203 204
      break;

205 206
    case 's':
      snr0 = atof(optarg);
207 208 209
#ifdef DEBUG_NR_PBCHSIM
      printf("Setting SNR0 to %f\n",snr0);
#endif
210 211 212 213 214
      break;

    case 'S':
      snr1 = atof(optarg);
      snr1set=1;
215 216 217
#ifdef DEBUG_NR_PBCHSIM
      printf("Setting SNR1 to %f\n",snr1);
#endif
218 219 220 221 222 223 224
      break;

      /*
      case 't':
      Td= atof(optarg);
      break;
      */
225
    /*case 'p':
226
      extended_prefix_flag=1;
227
      break;*/
228 229 230 231 232 233 234 235 236 237 238 239 240

      /*
      case 'r':
      ricean_factor = pow(10,-.1*atof(optarg));
      if (ricean_factor>1) {
        printf("Ricean factor must be between 0 and 1\n");
        exit(-1);
      }
      break;
      */
    case 'x':
      transmission_mode=atoi(optarg);

241 242
      if ((transmission_mode!=1) && (transmission_mode!=2) && (transmission_mode!=6)) {
        printf("Unsupported transmission mode %d. Exiting.\n",transmission_mode);
243 244 245 246 247 248 249 250 251
        exit(-1);
      }

      break;

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

      if ((n_tx==0) || (n_tx>2)) {
252
    	printf("Unsupported number of TX antennas %d. Exiting.\n", n_tx);
253 254 255 256 257 258 259 260 261
        exit(-1);
      }

      break;

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

      if ((n_rx==0) || (n_rx>2)) {
262
    	printf("Unsupported number of RX antennas %d. Exiting.\n", n_rx);
263 264 265 266 267
        exit(-1);
      }

      break;

268 269 270 271
    case 'M':
      SSB_positions = atoi(optarg);
      break;

272 273 274 275 276 277 278 279 280 281 282 283
    case 'N':
      Nid_cell = atoi(optarg);
      break;

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

    case 'F':
      input_fd = fopen(optarg,"r");

      if (input_fd==NULL) {
284
        printf("Problem with filename %s. Exiting.\n", optarg);
285 286 287 288 289 290 291 292 293 294 295 296
        exit(-1);
      }

      break;

    case 'P':
      pbch_phase = atoi(optarg);

      if (pbch_phase>3)
        printf("Illegal PBCH phase (0-3) got %d\n",pbch_phase);

      break;
297 298 299
      
    case 'I':
      run_initial_sync=1;
300
      target_error_rate=0.1;
301
      break;
302 303 304 305 306

    case 'L':
      loglvl = atoi(optarg);
      break;

307 308 309 310 311
    default:
    case 'h':
      printf("%s -h(elp) -p(extended_prefix) -N cell_id -f output_filename -F input_filename -g channel_model -n n_frames -t Delayspread -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");
312 313
      //printf("-p Use extended prefix mode\n");
      //printf("-d Use TDD\n");
314 315 316 317 318 319 320 321
      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("-t Delay spread for multipath channel\n");
      printf("-g [A,B,C,D,E,F,G] Use 3GPP SCM (A,B,C,D) or 36-101 (E-EPA,F-EVA,G-ETU) models (ignores delay spread and Ricean factor)\n");
      printf("-x Transmission mode (1,2,6 for the moment)\n");
      printf("-y Number of TX antennas used in eNB\n");
      printf("-z Number of RX antennas used in UE\n");
322 323
      //printf("-i Relative strength of first intefering eNB (in dB) - cell_id mod 3 = 1\n");
      //printf("-j Relative strength of second intefering eNB (in dB) - cell_id mod 3 = 2\n");
Francesco Mani's avatar
Francesco Mani committed
324
      printf("-o Carrier frequency offset in Hz\n");
325
      printf("-M Multiple SSB positions in burst\n");
326 327 328 329
      printf("-N Nid_cell\n");
      printf("-R N_RB_DL\n");
      printf("-O oversampling factor (1,2,4,8,16)\n");
      printf("-A Interpolation_filname Run with Abstraction to generate Scatter plot using interpolation polynomial in file\n");
330 331
      //printf("-C Generate Calibration information for Abstraction (effective SNR adjustment to remove Pe bias w.r.t. AWGN)\n");
      //printf("-f Output filename (.txt format) for Pe/SNR results\n");
332 333 334 335 336 337
      printf("-F Input filename (.txt format) for RX conformance testing\n");
      exit (-1);
      break;
    }
  }

338 339 340 341
  logInit();
  set_glog(loglvl);
  T_stdout = 1;

342 343 344
  if (snr1set==0)
    snr1 = snr0+10;

Raymond Knopp's avatar
Raymond Knopp committed
345
  printf("Initializing gNodeB for mu %d, N_RB_DL %d\n",mu,N_RB_DL);
346

347 348 349
  RC.gNB = (PHY_VARS_gNB**) malloc(sizeof(PHY_VARS_gNB *));
  RC.gNB[0] = malloc(sizeof(PHY_VARS_gNB));
  gNB = RC.gNB[0];
350
  frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH)
351 352 353
  frame_parms->nb_antennas_tx = n_tx;
  frame_parms->nb_antennas_rx = n_rx;
  frame_parms->N_RB_DL = N_RB_DL;
Raymond Knopp's avatar
Raymond Knopp committed
354
  frame_parms->N_RB_UL = N_RB_DL;
355
  frame_parms->Nid_cell = Nid_cell;
Francesco Mani's avatar
Francesco Mani committed
356 357
  frame_parms->nushift = Nid_cell%4;
  frame_parms->ssb_type = nr_ssb_type_C;
358

359
  nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions);
360 361
  phy_init_nr_gNB(gNB,0,0);

362 363
  uint8_t n_hf = 0;
  int cyclic_prefix_type = NFAPI_CP_NORMAL;
364

Francesco Mani's avatar
Francesco Mani committed
365
  double fs,bw,scs,eps;
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
  
  switch (mu) {
    case 1:
	scs = 30000;
	if (N_RB_DL == 217) { 
	    fs = 122.88e6;
	    bw = 80e6;
	    
	}					       
	else if (N_RB_DL == 245) {
	    fs = 122.88e6;
	    bw = 90e6;
	}
	else if (N_RB_DL == 273) {
	    fs = 122.88e6;
	    bw = 100e6;
	}
	else if (N_RB_DL == 106) { 
	    fs = 61.44e6;
	    bw = 40e6;
	}
	else AssertFatal(1==0,"Unsupported numerology for mu %d, N_RB %d\n",mu, N_RB_DL);
	break;
Raymond Knopp's avatar
Raymond Knopp committed
389 390
  }

Francesco Mani's avatar
Francesco Mani committed
391 392 393
  // cfo with respect to sub-carrier spacing
  eps = cfo/scs;

394 395
  // computation of integer and fractional FO to compare with estimation results
  int IFO;
Francesco Mani's avatar
Francesco Mani committed
396 397 398 399 400 401 402 403 404
  if(eps!=0.0){
	printf("Introducing a CFO of %lf relative to SCS of %d kHz\n",eps,(int)(scs/1000));
	if (eps>0)	
  	  IFO=(int)(eps+0.5);
	else
	  IFO=(int)(eps-0.5);
	printf("FFO = %lf; IFO = %d\n",eps-IFO,IFO);
  }

Raymond Knopp's avatar
Raymond Knopp committed
405 406 407 408 409 410 411 412 413 414
  gNB2UE = new_channel_desc_scm(n_tx,
                                n_rx,
                                channel_model,
 				fs, 
				bw, 
                                0,
                                0,
                                0);

  if (gNB2UE==NULL) {
415
	printf("Problem generating channel model. Exiting.\n");
Raymond Knopp's avatar
Raymond Knopp committed
416 417 418
    exit(-1);
  }

419
  frame_length_complex_samples = frame_parms->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
420 421
  frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP;

422 423 424 425 426 427
  s_re = malloc(2*sizeof(double*));
  s_im = malloc(2*sizeof(double*));
  r_re = malloc(2*sizeof(double*));
  r_im = malloc(2*sizeof(double*));
  txdata = malloc(2*sizeof(int*));

428 429 430 431 432 433 434 435 436 437 438 439
  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));

Raymond Knopp's avatar
Raymond Knopp committed
440
    printf("Allocating %d samples for txdata\n",frame_length_complex_samples);
441 442 443 444
    txdata[i] = malloc(frame_length_complex_samples*sizeof(int));
    bzero(r_re[i],frame_length_complex_samples*sizeof(int));
  
  }
445 446 447 448 449

  if (pbch_file_fd!=NULL) {
    load_pbch_desc(pbch_file_fd);
  }

450 451 452 453

  //configure UE
  UE = malloc(sizeof(PHY_VARS_NR_UE));
  memcpy(&UE->frame_parms,frame_parms,sizeof(NR_DL_FRAME_PARMS));
454
  //phy_init_nr_top(UE); //called from init_nr_ue_signal
455 456 457
  if (run_initial_sync==1)  UE->is_synchronized = 0;
  else                      UE->is_synchronized = 1;
                      
Raymond Knopp's avatar
Raymond Knopp committed
458 459
  UE->perfect_ce = 0;

460 461 462
  if(eps!=0.0)
	UE->UE_fo_compensation = 1; // if a frequency offset is set then perform fo estimation and compensation

463
  if (init_nr_ue_signal(UE, 1, 0) != 0) {
464 465 466 467
    printf("Error at UE NR initialisation\n");
    exit(-1);
  }

468
  nr_gold_pbch(UE);
469
  // generate signal
470
  if (input_fd==NULL) {
Raymond Knopp's avatar
Raymond Knopp committed
471
    gNB->pbch_configured = 1;
472
 
473
    gNB->ssb_pdu.ssb_pdu_rel15.bchPayload = 0;
474

475
    for (int slot=0;slot<frame_parms->slots_per_frame;slot++) {
476 477
    	for (aa=0; aa<gNB->frame_parms.nb_antennas_tx; aa++)
    		memset(gNB->common_vars.txdataF[aa],0,frame_parms->samples_per_slot_wCP*sizeof(int32_t));
478
      
479
    	nr_common_signal_procedures (gNB,frame,slot);
480
      
481
    	for (aa=0; aa<gNB->frame_parms.nb_antennas_tx; aa++) {
482
    		if (cyclic_prefix_type == 1) {
483
    			PHY_ofdm_mod(gNB->common_vars.txdataF[aa],
484 485 486 487 488
    			             &txdata[aa][slot*frame_parms->samples_per_slot],
				     frame_parms->ofdm_symbol_size,
				     12,
				     frame_parms->nb_prefix_samples,
				     CYCLIC_PREFIX);
489 490
    		} else {
    			nr_normal_prefix_mod(gNB->common_vars.txdataF[aa],
491 492 493
    			                     &txdata[aa][slot*frame_parms->samples_per_slot],
			                     14,
			                     frame_parms);
494 495
    		}
    	}
496
    }
497 498 499 500 501

    LOG_M("txsigF0.m","txsF0", gNB->common_vars.txdataF[0],frame_length_complex_samples_no_prefix,1,1);
    if (gNB->frame_parms.nb_antennas_tx>1)
      LOG_M("txsigF1.m","txsF1", gNB->common_vars.txdataF[1],frame_length_complex_samples_no_prefix,1,1);

502 503
  } else {
    printf("Reading %d samples from file to antenna buffer %d\n",frame_length_complex_samples,0);
Francesco Mani's avatar
Francesco Mani committed
504
    UE->UE_fo_compensation = 1; // perform fo compensation when samples from file are used
505 506 507 508 509
    if (fread(txdata[0],
	      sizeof(int32_t),
	      frame_length_complex_samples,
	      input_fd) != frame_length_complex_samples) {
      printf("error reading from file\n");
510
      //exit(-1);
511 512
    }
  }
513

514 515 516
  LOG_M("txsig0.m","txs0", txdata[0],frame_length_complex_samples,1,1);
  if (gNB->frame_parms.nb_antennas_tx>1)
    LOG_M("txsig1.m","txs1", txdata[1],frame_length_complex_samples,1,1);
517

518 519 520
  if (output_fd) 
    fwrite(txdata[0],sizeof(int32_t),frame_length_complex_samples,output_fd);

521 522 523
  /*int txlev = signal_energy(&txdata[0][5*frame_parms->ofdm_symbol_size + 4*frame_parms->nb_prefix_samples + frame_parms->nb_prefix_samples0],
		  	  	  	  	    frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples);
  printf("txlev %d (%f)\n",txlev,10*log10(txlev));*/
524

Francesco Mani's avatar
Francesco Mani committed
525

526 527
  for (i=0; i<frame_length_complex_samples; i++) {
    for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
528 529
      r_re[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)]);
      r_im[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)+1]);
530
    }
Raymond Knopp's avatar
Raymond Knopp committed
531
  }
532 533 534 535
  
  for (SNR=snr0; SNR<snr1; SNR+=.2) {

    n_errors = 0;
536
    n_errors_payload = 0;
537 538

    for (trial=0; trial<n_trials; trial++) {
539 540
      // multipath channel
      //multipath_channel(gNB2UE,s_re,s_im,r_re,r_im,frame_length_complex_samples,0);
541 542
      
      //AWGN
543
      sigma2_dB = 20*log10((double)AMP/4)-SNR;
544
      sigma2 = pow(10,sigma2_dB/10);
545
      //printf("sigma2 %f (%f dB), tx_lev %f (%f dB)\n",sigma2,sigma2_dB,txlev,10*log10((double)txlev));
Raymond Knopp's avatar
Raymond Knopp committed
546

Francesco Mani's avatar
Francesco Mani committed
547 548 549 550 551 552 553 554
      if(eps!=0.0)
        rf_rx(r_re,  // real part of txdata
           r_im,  // imag part of txdata
           NULL,  // interference real part
           NULL, // interference imag part
           0,  // interference power
           frame_parms->nb_antennas_rx,  // number of rx antennas
           frame_length_complex_samples,  // number of samples in frame
555
           1.0e9/fs,   //sampling time (ns)
Francesco Mani's avatar
Francesco Mani committed
556 557 558 559 560 561 562 563 564 565 566 567
           cfo,	// frequency offset in Hz
           0.0, // drift (not implemented)
           0.0, // noise figure (not implemented)
           0.0, // rx gain in dB ?
           200, // 3rd order non-linearity in dB ?
           &ip, // initial phase
           30.0e3,  // phase noise cutoff in kHz
           -500.0, // phase noise amplitude in dBc
           0.0,  // IQ imbalance (dB),
	   0.0); // IQ phase imbalance (rad)

   
568 569 570
      for (i=0; i<frame_length_complex_samples; i++) {
	for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
	  
571 572
	  ((short*) UE->common_vars.rxdata[aa])[2*i]   = (short) ((r_re[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0)));
	  ((short*) UE->common_vars.rxdata[aa])[2*i+1] = (short) ((r_im[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0)));
573 574
	}
      }
575 576

      if (n_trials==1) {
577
	LOG_M("rxsig0.m","rxs0", UE->common_vars.rxdata[0],frame_parms->samples_per_frame,1,1);
578
	if (gNB->frame_parms.nb_antennas_tx>1)
579
	  LOG_M("rxsig1.m","rxs1", UE->common_vars.rxdata[1],frame_parms->samples_per_frame,1,1);
580
      }
581

582
      if (UE->is_synchronized == 0) {
laurent's avatar
fixes  
laurent committed
583
	UE_nr_rxtx_proc_t proc={0};
584
	ret = nr_initial_sync(&proc, UE, normal_txrx,1);
585 586 587 588 589
	printf("nr_initial_sync1 returns %d\n",ret);
	if (ret<0) n_errors++;
      }
      else {
	UE->rx_offset=0;
590 591
	uint8_t ssb_index = 0;
        while (!((SSB_positions >> ssb_index) & 0x01)) ssb_index++;  // to select the first transmitted ssb
592
	UE->symbol_offset = nr_get_ssb_start_symbol(frame_parms, ssb_index);
593
        int ssb_slot = (ssb_index/2)+(n_hf*frame_parms->slots_per_frame);
594
	for (int i=UE->symbol_offset+1; i<UE->symbol_offset+4; i++) {
595
	  nr_slot_fep(UE,
596 597
	  	      i%frame_parms->symbols_per_slot,
		      ssb_slot,
598
		      0,
Florian Kaltenberger's avatar
Florian Kaltenberger committed
599
		      0);
600

601
          nr_pbch_channel_estimation(UE,0,ssb_slot,i%frame_parms->symbols_per_slot,i-(UE->symbol_offset+1),ssb_index%8,n_hf);
602

603
        }
laurent's avatar
fixes  
laurent committed
604
	UE_nr_rxtx_proc_t proc={0};
Francesco Mani's avatar
Francesco Mani committed
605

606
        ret = nr_rx_pbch(UE,
laurent's avatar
fixes  
laurent committed
607
	                 &proc,
608 609 610 611 612 613
		         UE->pbch_vars[0],
		         frame_parms,
		         0,
		         ssb_index%8,
                         SISO,
                         UE->high_speed_flag);
Florian Kaltenberger's avatar
WIP  
Florian Kaltenberger committed
614

615 616 617
	if (ret==0) {
	  //UE->rx_ind.rx_indication_body->mib_pdu.ssb_index;  //not yet detected automatically
	  //UE->rx_ind.rx_indication_body->mib_pdu.ssb_length; //Lmax, not yet detected automatically
618 619 620
	  uint8_t gNB_xtra_byte=0;
	  for (int i=0; i<8; i++)
	    gNB_xtra_byte |= ((gNB->pbch.pbch_a>>(31-i))&1)<<(7-i);
Florian Kaltenberger's avatar
Florian Kaltenberger committed
621 622

	  payload_ret = (UE->pbch_vars[0]->xtra_byte == gNB_xtra_byte);
Guy De Souza's avatar
Guy De Souza committed
623
	  for (i=0;i<3;i++){
624
	    payload_ret += (UE->pbch_vars[0]->decoded_output[i] == (gNB->ssb_pdu.ssb_pdu_rel15.bchPayload>>(8*i)));
625
	  } 
Guy De Souza's avatar
Guy De Souza committed
626
	  //printf("xtra byte gNB: 0x%02x UE: 0x%02x\n",gNB_xtra_byte, UE->rx_ind.rx_indication_body->mib_pdu.additional_bits);
627
	  //printf("ret %d\n", payload_ret);
628 629
	  if (payload_ret!=4) 
	    n_errors_payload++;
630 631
	}

632
	if (ret!=0) n_errors++;
633
      }
634
    } //noise trials
635
    printf("SNR %f: trials %d, n_errors_crc = %d, n_errors_payload %d\n", SNR,n_trials,n_errors,n_errors_payload);
636

637
    if (((float)n_errors/(float)n_trials <= target_error_rate) && (n_errors_payload==0)) {
638 639 640 641
      printf("PBCH test OK\n");
      break;
    }
      
642 643 644
    if (n_trials==1)
      break;

645 646 647 648 649 650 651
  } // NSR

  for (i=0; i<2; i++) {
    free(s_re[i]);
    free(s_im[i]);
    free(r_re[i]);
    free(r_im[i]);
652
    free(txdata[i]);
653 654 655 656 657 658
  }

  free(s_re);
  free(s_im);
  free(r_re);
  free(r_im);
659
  free(txdata);
660

661
  if (output_fd)
662 663
    fclose(output_fd);

664 665 666
  if (input_fd)
    fclose(input_fd);

667 668 669
  return(n_errors);

}