pucchsim.c 20.7 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 28 29 30 31 32 33 34 35 36 37
/*
 * 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>
#include "common/config/config_userapi.h"
#include "common/utils/LOG/log.h"
#include "common/ran_context.h" 
#include "PHY/types.h"
#include "PHY/defs_nr_common.h"
#include "PHY/defs_nr_UE.h"
#include "PHY/defs_gNB.h"
#include "PHY/NR_REFSIG/refsig_defs_ue.h"
#include "PHY/MODULATION/modulation_eNB.h"
#include "PHY/MODULATION/modulation_UE.h"
38
#include "PHY/NR_ESTIMATION/nr_ul_estimation.h"
39
#include "PHY/INIT/phy_init.h"
cig's avatar
cig committed
40
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
41 42
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
#include "PHY/NR_UE_TRANSPORT/pucch_nr.h"
43 44 45 46 47
#include "SCHED_NR/sched_nr.h"
#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"
48 49 50 51

PHY_VARS_gNB *gNB;
PHY_VARS_NR_UE *UE;
RAN_CONTEXT_t RC;
prasanth's avatar
prasanth committed
52
openair0_config_t openair0_cfg[MAX_CARDS];
53 54
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];

55
double cpuf;
56
uint8_t nfapi_mode = 0;
yilmazt's avatar
yilmazt committed
57
uint16_t NB_UE_INST = 1;
58 59
uint8_t const nr_rv_round_map[4] = {0, 2, 1, 3};
uint8_t const nr_rv_round_map_ue[4] = {0, 2, 1, 3};
60 61 62 63

// needed for some functions
PHY_VARS_NR_UE * PHY_vars_UE_g[1][1]={{NULL}};

64 65
void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) {}

66 67 68
int main(int argc, char **argv)
{
  char c;
69
  int i,aa=0;//,l;
70 71 72
  double sigma2, sigma2_dB=10,SNR,snr0=-2.0,snr1=2.0;
  double cfo=0;
  uint8_t snr1set=0;
73
  int **txdataF,**rxdataF;
74
  double **s_re,**s_im,**r_re,**r_im;
yilmazt's avatar
yilmazt committed
75 76
  //int sync_pos, sync_pos_slot;
  //FILE *rx_frame_file;
77
  FILE *output_fd = NULL;
78
  //uint8_t write_output_file=0;
79 80
  //int result;
  //int freq_offset;
81 82
  //int subframe_offset;
  //char fname[40], vname[40];
83
  int trial,n_trials=100,n_errors=0,ack_nack_errors=0,sr_errors=0;
84 85
  uint8_t transmission_mode = 1,n_tx=1,n_rx=1;
  uint16_t Nid_cell=0;
prasanth's avatar
prasanth committed
86
  uint64_t SSB_positions=0x01;
87
  channel_desc_t *UE2gNB;
88
  int format=0;
yilmazt's avatar
yilmazt committed
89
  //uint8_t extended_prefix_flag=0;
90
  FILE *input_fd=NULL;
91
  //uint8_t nacktoack_flag=0;
92 93
  int16_t amp=0x7FFF;
  int nr_tti_tx=0; 
Francesco Mani's avatar
Francesco Mani committed
94
  uint64_t actual_payload=0,payload_received;
95 96 97 98 99
  int nr_bit=1; // maximum value possible is 2
  uint8_t m0=0;// higher layer paramater initial cyclic shift
  uint8_t nrofSymbols=1; //number of OFDM symbols can be 1-2 for format 1
  uint8_t startingSymbolIndex=0; // resource allocated see 9.2.1, 38.213 for more info.should be actually present in the resource set provided
  uint16_t startingPRB=0,startingPRB_intraSlotHopping=0; //PRB number not sure see 9.2.1, 38.213 for more info. Should be actually present in the resource set provided
100
  uint16_t nrofPRB=2;
101
  uint8_t timeDomainOCC=0;
102
  SCM_t channel_model=AWGN;//Rayleigh1_anticorr;
103 104

  double DS_TDL = .03;
105
  
106
  int N_RB_DL=273,mu=1;
107
  float target_error_rate=0.001;
108
  int frame_length_complex_samples;
yilmazt's avatar
yilmazt committed
109
  //int frame_length_complex_samples_no_prefix;
110
  NR_DL_FRAME_PARMS *frame_parms;
yilmazt's avatar
yilmazt committed
111
  //unsigned char frame_type = 0;
112
  int loglvl=OAILOG_WARNING;
113
  int sr_flag = 0;
114 115 116

  cpuf = get_cpu_freq_GHz();

yilmazt's avatar
yilmazt committed
117 118
  if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == 0) {
    exit_fun("[NR_PUCCHSIM] Error, configuration module init failed\n");
119 120 121
  }

  randominit(0);
yilmazt's avatar
yilmazt committed
122
  logInit();
123

124
  while ((c = getopt (argc, argv, "f:hA:f:g:i:I:P:B:b:T:m:n:r:o:s:S:x:y:z:N:F:GR:IL:q:c")) != -1) {
125 126
    switch (c) {
    case 'f':
127
      //write_output_file=1;
128 129 130 131 132 133 134 135
      output_fd = fopen(optarg,"w");

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

yilmazt's avatar
yilmazt committed
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

    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;
167 168 169 170 171 172 173 174 175 176 177 178 179 180
      case 'H':
        channel_model = TDL_C;
	DS_TDL = .030; // 30 ns
	break;
  
      case 'I':
	channel_model = TDL_C;
	DS_TDL = .3;  // 300ns
        break;
     
      case 'J':
	channel_model=TDL_D;
	DS_TDL = .03;
	break;
181 182

      default:
183
        printf("Unsupported channel model!\n");
184 185 186 187 188 189 190 191 192 193
        exit(-1);
      }
      break;

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

    case 'o':
      cfo = atof(optarg);
194
      printf("Setting CFO to %f Hz\n",cfo);
195 196 197 198
      break;

    case 's':
      snr0 = atof(optarg);
199
      printf("Setting SNR0 to %f\n",snr0);
200 201 202 203 204
      break;

    case 'S':
      snr1 = atof(optarg);
      snr1set=1;
205
      printf("Setting SNR1 to %f\n",snr1);
206 207 208
      break;

      /*
yilmazt's avatar
yilmazt committed
209
    case 't':
210 211
      Td= atof(optarg);
      break;
yilmazt's avatar
yilmazt committed
212

213 214 215 216
    case 'p':
      extended_prefix_flag=1;
      break;

yilmazt's avatar
yilmazt committed
217 218 219 220 221
    case 'd':
      frame_type = 1;
      break;

    case 'r':
222 223 224 225 226 227 228 229 230 231 232 233 234
      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);

      if ((transmission_mode!=1) &&
          (transmission_mode!=2) &&
          (transmission_mode!=6)) {
235
        printf("Unsupported transmission mode %d\n",transmission_mode);
236 237 238 239 240 241 242 243
        exit(-1);
      }
      break;

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

      if ((n_tx==0) || (n_tx>2)) {
244
        printf("Unsupported number of tx antennas %d\n",n_tx);
245 246 247 248 249 250 251 252
        exit(-1);
      }
      break;

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

      if ((n_rx==0) || (n_rx>2)) {
253
        printf("Unsupported number of rx antennas %d\n",n_rx);
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
        exit(-1);
      }
      break;

    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) {
        printf("Problem with filename %s\n",optarg);
        exit(-1);
      }
      break;

    case 'L':
      loglvl = atoi(optarg);
      break;
278 279 280
    case 'i':
      nrofSymbols=(uint8_t)atoi(optarg);
      break;
Francesco Mani's avatar
Francesco Mani committed
281 282 283 284 285 286
    case 'I':
      startingSymbolIndex=(uint8_t)atoi(optarg);
      break;
    case 'r':
      startingPRB=atoi(optarg);
      break;
287 288 289
    case 'q':
      nrofPRB=atoi(optarg);
      break;
290 291 292
    case 'P':
      format=atoi(optarg);
      break;
Francesco Mani's avatar
Francesco Mani committed
293 294 295
    case 'm':
      m0=atoi(optarg);
      break;
296 297 298
    case 'b':
      nr_bit=atoi(optarg);
      break;
299 300 301
    case 'c':
      sr_flag=1;
      break;
Francesco Mani's avatar
Francesco Mani committed
302 303 304
    case 'B':
      actual_payload=atoi(optarg);
      break;
305
    case 'T':
306
      //nacktoack_flag=(uint8_t)atoi(optarg);
307 308
      target_error_rate=0.001;
      break;
309 310
    default:
    case 'h':
yilmazt's avatar
yilmazt committed
311
      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]);
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
      printf("-h This message\n");
      printf("-p Use extended prefix mode\n");
      printf("-d Use TDD\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("-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");
      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");
      printf("-o Carrier frequency offset in Hz\n");
      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");
yilmazt's avatar
yilmazt committed
330
      //printf("-C Generate Calibration information for Abstraction (effective SNR adjustment to remove Pe bias w.r.t. AWGN)\n");
331 332
      printf("-f Output filename (.txt format) for Pe/SNR results\n");
      printf("-F Input filename (.txt format) for RX conformance testing\n");
333
      printf("-i Enter number of ofdm symbols for pucch\n");
Francesco Mani's avatar
Francesco Mani committed
334
      printf("-I Starting symbol index for pucch\n");
335 336
      printf("-r PUCCH starting PRB\n");
      printf("-q PUCCH number of PRB\n");
337 338
      printf("-P Enter the format of PUCCH\n");
      printf("-b number of HARQ bits (1-2)\n");
Francesco Mani's avatar
Francesco Mani committed
339 340
      printf("-B payload to be transmitted on PUCCH\n");
      printf("-m initial cyclic shift m0\n");
341
      printf("-T to check nacktoack miss for format 1");
342 343 344
      exit (-1);
      break;
    }
yilmazt's avatar
yilmazt committed
345
  }
346

347 348
  set_glog(loglvl);

yilmazt's avatar
yilmazt committed
349
  if (snr1set==0) snr1 = snr0+10;
350 351 352

  printf("Initializing gNodeB for mu %d, N_RB_DL %d\n",mu,N_RB_DL);

353
  if((format!=0) && (format!=1) && (format!=2)){
Francesco Mani's avatar
Francesco Mani committed
354 355 356 357
    printf("PUCCH format %d not supported\n",format);
    exit(0); 
  }

358
  AssertFatal(((format < 2)&&(nr_bit<3)&&(actual_payload<4)) ||
359
	      ((format == 2)&&(nr_bit>2)&&(nr_bit<65)),"illegal combination format %d, nr_bit %d\n",
360
	      format,nr_bit);
Francesco Mani's avatar
Francesco Mani committed
361

362
  actual_payload &= ((1<<nr_bit)-1);
Francesco Mani's avatar
Francesco Mani committed
363 364

  printf("Transmitted payload is %ld\n",actual_payload);
365

366 367 368
  RC.gNB = (PHY_VARS_gNB**) malloc(sizeof(PHY_VARS_gNB *));
  RC.gNB[0] = malloc(sizeof(PHY_VARS_gNB));
  gNB = RC.gNB[0];
369
  memset((void*)gNB,0,sizeof(*gNB));
370 371 372 373 374 375 376
  frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH)
  frame_parms->nb_antennas_tx = n_tx;
  frame_parms->nb_antennas_rx = n_rx;
  frame_parms->N_RB_DL = N_RB_DL;
  frame_parms->N_RB_UL = N_RB_DL;
  frame_parms->Nid_cell = Nid_cell;

377 378 379
  nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
  cfg->carrier_config.num_tx_ant.value = n_tx;
  cfg->carrier_config.num_rx_ant.value = n_rx;
prasanth's avatar
prasanth committed
380
  nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions);
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
  phy_init_nr_gNB(gNB,0,0);

  double fs,bw,scs,eps;

  if (mu == 1 && N_RB_DL == 217) { 
    fs = 122.88e6;
    bw = 80e6;
    scs = 30000;
  }					       
  else if (mu == 1 && N_RB_DL == 245) {
    fs = 122.88e6;
    bw = 90e6;
    scs = 30000;
  }
  else if (mu == 1 && N_RB_DL == 273) {
    fs = 122.88e6;
    bw = 100e6;
    scs = 30000;
  }
  else if (mu == 1 && N_RB_DL == 106) { 
    fs = 61.44e6;
    bw = 40e6;
    scs = 30000;
  }
  else AssertFatal(1==0,"Unsupported numerology for mu %d, N_RB %d\n",mu, N_RB_DL);

  // cfo with respect to sub-carrier spacing
  eps = cfo/scs;

  // computation of integer and fractional FO to compare with estimation results
  int IFO;
  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);
  }

421
  UE2gNB = new_channel_desc_scm(n_tx, n_rx, channel_model, fs, bw, DS_TDL,0, 0, 0);
422

423
  if (UE2gNB==NULL) {
424
    printf("Problem generating channel model. Exiting.\n");
425 426 427 428
    exit(-1);
  }

  frame_length_complex_samples = frame_parms->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
yilmazt's avatar
yilmazt committed
429
  //frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP;
430 431 432 433 434

  s_re = malloc(2*sizeof(double*));
  s_im = malloc(2*sizeof(double*));
  r_re = malloc(2*sizeof(double*));
  r_im = malloc(2*sizeof(double*));
435 436 437 438
  txdataF = malloc(2*sizeof(int*));
  rxdataF = malloc(2*sizeof(int*));
  gNB->common_vars.rxdataF=rxdataF;
  memcpy((void*)&gNB->frame_parms,(void*)frame_parms,sizeof(frame_parms));
439 440 441 442 443 444 445 446 447 448 449 450
  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));

451
    printf("Allocating %d samples for txdataF/rxdataF\n",14*frame_parms->ofdm_symbol_size);
452
    txdataF[i] = memalign(32,14*frame_parms->ofdm_symbol_size*sizeof(int));
453
    bzero(txdataF[i],14*frame_parms->ofdm_symbol_size*sizeof(int));
454
    rxdataF[i] = memalign(32,14*frame_parms->ofdm_symbol_size*sizeof(int));
455
    bzero(rxdataF[i],14*frame_parms->ofdm_symbol_size*sizeof(int));
456 457 458 459 460 461
  }


  //configure UE
  UE = malloc(sizeof(PHY_VARS_NR_UE));
  memcpy(&UE->frame_parms,frame_parms,sizeof(NR_DL_FRAME_PARMS));
462
  UE->pucch_config_common_nr->hoppingId = Nid_cell;
463 464 465 466 467 468 469 470 471 472 473 474
  //phy_init_nr_top(UE); //called from init_nr_ue_signal
                      
  UE->perfect_ce = 0;

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

  if (init_nr_ue_signal(UE, 1, 0) != 0)
  {
    printf("Error at UE NR initialisation\n");
    exit(-1);
  }
475 476
  uint8_t mcs=0;
  startingPRB_intraSlotHopping=N_RB_DL-1;
477
  pucch_GroupHopping_t PUCCH_GroupHopping=UE->pucch_config_common_nr->pucch_GroupHopping;
478 479
  uint32_t hopping_id=UE->pucch_config_common_nr->hoppingId;
  uint32_t dmrs_scrambling_id = 0, data_scrambling_id=0;
480
  //t_nrPolar_params *currentPtr;
481

Francesco Mani's avatar
Francesco Mani committed
482 483
  int shift = 0;

Francesco Mani's avatar
Francesco Mani committed
484
  if(format==0){
Francesco Mani's avatar
Francesco Mani committed
485 486
    if (sr_flag)
      shift = 1<<nr_bit;
487 488 489
    if (nr_bit ==0) 
      mcs=table1_mcs[0];
    else if(nr_bit==1)
Francesco Mani's avatar
Francesco Mani committed
490
      mcs=table1_mcs[actual_payload+shift];
Francesco Mani's avatar
Francesco Mani committed
491
    else if(nr_bit==2)
Francesco Mani's avatar
Francesco Mani committed
492
      mcs=table2_mcs[actual_payload+shift];
laurent's avatar
laurent committed
493
    else AssertFatal(1==0,"Either nr_bit %d or sr_flag %d must be non-zero\n", nr_bit, sr_flag);
494
  }
495 496
  else if (format == 2 && nr_bit > 11) gNB->uci_polarParams = nr_polar_params(2, nr_bit, nrofPRB, 1, NULL);
  
497
  for(SNR=snr0;SNR<=snr1;SNR=SNR+1){
498
    ack_nack_errors=0;
499
    sr_errors=0;
500 501
    n_errors = 0;
    for (trial=0; trial<n_trials; trial++) {
502
      bzero(txdataF[aa],frame_parms->ofdm_symbol_size*sizeof(int));
503
      if(format==0){
Francesco Mani's avatar
Francesco Mani committed
504
        nr_generate_pucch0(UE,txdataF,frame_parms,PUCCH_GroupHopping,hopping_id,amp,nr_tti_tx,m0,mcs,nrofSymbols,startingSymbolIndex,startingPRB);
505
      }
506
      else if (format == 1){
507
        nr_generate_pucch1(UE,txdataF,frame_parms,UE->pucch_config_dedicated,actual_payload,amp,nr_tti_tx,m0,nrofSymbols,startingSymbolIndex,startingPRB,startingPRB_intraSlotHopping,0,nr_bit);	
508
      }
509 510 511
      else {
	nr_generate_pucch2(UE,0x1234,dmrs_scrambling_id,data_scrambling_id,txdataF,frame_parms,UE->pucch_config_dedicated,actual_payload,amp,nr_tti_tx,nrofSymbols,startingSymbolIndex,nrofPRB,startingPRB,nr_bit);	
      }
512 513 514 515 516
      
      int txlev = signal_energy(&txdataF[aa][startingSymbolIndex*frame_parms->ofdm_symbol_size],
				frame_parms->ofdm_symbol_size);
      //      printf("txlev %d (%d dB), offset %d\n",txlev,dB_fixed(txlev),startingSymbolIndex*frame_parms->ofdm_symbol_size);
	    
517 518 519
      // note : this scaling
      int nb_re = (format == 0 || format == 1)? 12 : 12*nrofPRB;
      sigma2_dB = 10*log10((double)txlev*UE->frame_parms.ofdm_symbol_size/nb_re)-SNR;
Raymond Knopp's avatar
Raymond Knopp committed
520 521
      sigma2 = pow(10,sigma2_dB/10);
      
522 523 524
      for(i=startingSymbolIndex*frame_parms->ofdm_symbol_size; i<(startingSymbolIndex+1)*frame_parms->ofdm_symbol_size; i++) {
        ((int16_t*)rxdataF[aa])[i<<1] = (int16_t)(100.0*((double)(((int16_t *)txdataF[aa])[(i<<1)]) + sqrt(sigma2/2)*gaussdouble(0.0,1.0))/sqrt((double)txlev));
        ((int16_t*)rxdataF[aa])[1+(i<<1)]=(int16_t)(100.0*((double)(((int16_t *)txdataF[aa])[(i<<1)+1])+ sqrt(sigma2/2)*gaussdouble(0.0,1.0))/sqrt((double)txlev));
525
      }
526 527
      int rxlev = signal_energy(&rxdataF[aa][startingSymbolIndex*frame_parms->ofdm_symbol_size],
				frame_parms->ofdm_symbol_size);
528 529 530 531 532 533 534 535 536

      // noise measurement
      gNB->ulmask_symb = startingSymbolIndex;
      for (int rb=0; rb<nrofPRB; rb++) {
        int rb2 = rb+startingPRB;
        gNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31));
      }
      gNB_I0_measurements(gNB);

537
      if (n_trials==1) printf("rxlev %d (%d dB), sigma2 %f dB, SNR %f, TX %f\n",rxlev,dB_fixed(rxlev),sigma2_dB,SNR,10*log10((double)txlev*UE->frame_parms.ofdm_symbol_size/12));
538
      if(format==0){
Raymond Knopp's avatar
Raymond Knopp committed
539 540
	nfapi_nr_uci_pucch_pdu_format_0_1_t uci_pdu;
	nfapi_nr_pucch_pdu_t pucch_pdu;
541
	pucch_pdu.subcarrier_spacing    = 1;
Raymond Knopp's avatar
Raymond Knopp committed
542 543 544
	pucch_pdu.group_hop_flag        = PUCCH_GroupHopping&1;
	pucch_pdu.sequence_hop_flag     = (PUCCH_GroupHopping>>1)&1;
	pucch_pdu.bit_len_harq          = nr_bit;
545 546
	pucch_pdu.bit_len_csi_part1     = 0;
	pucch_pdu.bit_len_csi_part2     = 0;
547
	pucch_pdu.sr_flag               = sr_flag;
Raymond Knopp's avatar
Raymond Knopp committed
548
	pucch_pdu.nr_of_symbols         = nrofSymbols;
549
	pucch_pdu.hopping_id            = hopping_id;
Raymond Knopp's avatar
Raymond Knopp committed
550 551 552
	pucch_pdu.initial_cyclic_shift  = 0;
	pucch_pdu.start_symbol_index    = startingSymbolIndex;
	pucch_pdu.prb_start             = startingPRB;
553
        nr_decode_pucch0(gNB,nr_tti_tx,&uci_pdu,&pucch_pdu);
554 555 556 557 558 559 560 561 562 563 564
        if(sr_flag==1){
          if (uci_pdu.sr->sr_indication == 0 || uci_pdu.sr->sr_confidence_level == 1)
            sr_errors+=1;
        }
        if(nr_bit>0){
          if(nr_bit==1)
            ack_nack_errors+=(actual_payload^uci_pdu.harq->harq_list[0].harq_value);
          else
            ack_nack_errors+=(((actual_payload&1)^uci_pdu.harq->harq_list[0].harq_value)+((actual_payload>>1)^uci_pdu.harq->harq_list[1].harq_value));
	  free(uci_pdu.harq->harq_list);
        }
565
      }
566
      else if (format==1) {
567 568 569 570
        nr_decode_pucch1(rxdataF,PUCCH_GroupHopping,hopping_id,
                         &(payload_received),frame_parms,amp,nr_tti_tx,
                         m0,nrofSymbols,startingSymbolIndex,startingPRB,
                         startingPRB_intraSlotHopping,timeDomainOCC,nr_bit);
yilmazt's avatar
yilmazt committed
571 572 573 574
        if(nr_bit==1)
          ack_nack_errors+=((actual_payload^payload_received)&1);
        else
          ack_nack_errors+=((actual_payload^payload_received)&1) + (((actual_payload^payload_received)&2)>>1);
575
      }
576 577 578 579 580 581 582
      else if (format==2) {
	nfapi_nr_uci_pucch_pdu_format_2_3_4_t uci_pdu;
	nfapi_nr_pucch_pdu_t pucch_pdu;
	pucch_pdu.rnti = 0x1234;
	pucch_pdu.subcarrier_spacing    = 1;
	pucch_pdu.group_hop_flag        = PUCCH_GroupHopping&1;
	pucch_pdu.sequence_hop_flag     = (PUCCH_GroupHopping>>1)&1;
583 584 585
	pucch_pdu.bit_len_csi_part1     = nr_bit;
	pucch_pdu.bit_len_harq          = 0;
	pucch_pdu.bit_len_csi_part2     = 0;
586 587 588 589 590 591 592 593 594 595
	pucch_pdu.sr_flag               = 0;
	pucch_pdu.nr_of_symbols         = nrofSymbols;
	pucch_pdu.hopping_id            = hopping_id;
	pucch_pdu.initial_cyclic_shift  = 0;
	pucch_pdu.start_symbol_index    = startingSymbolIndex;
	pucch_pdu.prb_size              = nrofPRB;
	pucch_pdu.prb_start             = startingPRB;
	pucch_pdu.dmrs_scrambling_id    = dmrs_scrambling_id;
	pucch_pdu.data_scrambling_id    = data_scrambling_id;
        nr_decode_pucch2(gNB,nr_tti_tx,&uci_pdu,&pucch_pdu);
596 597 598 599
	int csi_part1_bytes=pucch_pdu.bit_len_csi_part1>>3;
	if ((pucch_pdu.bit_len_csi_part1&7) > 0) csi_part1_bytes++;
	for (int i=0;i<csi_part1_bytes;i++) {
	  if (uci_pdu.csi_part1.csi_part1_payload[i] != ((uint8_t*)&actual_payload)[i]) {
600 601 602
	    ack_nack_errors++;
	    break;
	  }
603 604
	}
	free(uci_pdu.csi_part1.csi_part1_payload);
605 606

      }
607 608
      n_errors=((actual_payload^payload_received)&1)+(((actual_payload^payload_received)&2)>>1)+(((actual_payload^payload_received)&4)>>2)+n_errors;
    }
609 610 611 612 613
    if (sr_flag == 1)
      printf("SR: SNR=%f, n_trials=%d, n_bit_errors=%d\n",SNR,n_trials,sr_errors);
    if(nr_bit > 0)
      printf("ACK/NACK: SNR=%f, n_trials=%d, n_bit_errors=%d\n",SNR,n_trials,ack_nack_errors);
    if((float)(ack_nack_errors+sr_errors)/(float)(n_trials)<=target_error_rate){
614 615 616
      printf("PUCCH test OK\n");
      break;
    }
617
  }
yilmazt's avatar
yilmazt committed
618

619 620 621 622 623
  for (i=0; i<2; i++) {
    free(s_re[i]);
    free(s_im[i]);
    free(r_re[i]);
    free(r_im[i]);
624 625
    free(txdataF[i]);
    free(rxdataF[i]);
626 627 628 629 630
  }
  free(s_re);
  free(s_im);
  free(r_re);
  free(r_im);
631 632
  free(txdataF);
  free(rxdataF);
633

yilmazt's avatar
yilmazt committed
634 635
  if (output_fd) fclose(output_fd);
  if (input_fd)  fclose(input_fd);
636 637 638

  return(n_errors);
}