dlsim.c 33.1 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
/*
 * 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 <fcntl.h>
23 24
#include <math.h>
#include <string.h>
25 26
#include <sys/ioctl.h>
#include <sys/mman.h>
27 28
#include <unistd.h>
#include "common/ran_context.h"
29 30
#include "common/config/config_userapi.h"
#include "common/utils/LOG/log.h"
31 32 33 34 35 36
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
#include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
#include "openair2/LAYER2/NR_MAC_UE/mac_defs.h"
#include "openair2/LAYER2/NR_MAC_UE/mac_extern.h"
#include "openair2/LAYER2/NR_MAC_UE/mac_proto.h"
#include "PHY/defs_gNB.h"
37 38
#include "PHY/defs_nr_common.h"
#include "PHY/defs_nr_UE.h"
39
#include "PHY/phy_vars_nr_ue.h"
40 41
#include "PHY/types.h"
#include "PHY/INIT/phy_init.h"
42 43
#include "PHY/MODULATION/modulation_eNB.h"
#include "PHY/MODULATION/modulation_UE.h"
44 45
#include "PHY/NR_REFSIG/nr_mod_table.h"
#include "PHY/NR_REFSIG/refsig_defs_ue.h"
46
#include "PHY/NR_TRANSPORT/nr_transport.h"
47
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
48
#include "SCHED_NR/fapi_nr_l1.h"
49
#include "SCHED_NR/sched_nr.h"
50
#include "SCHED_NR_UE/defs.h"
51 52 53 54
#include "SCHED_NR_UE/fapi_nr_ue_l1.h"
#include "NR_PHY_INTERFACE/NR_IF_Module.h"
#include "NR_UE_PHY_INTERFACE/NR_IF_Module.h"

55
#include "LAYER2/NR_MAC_UE/mac_proto.h"
yilmazt's avatar
yilmazt committed
56 57
//#include "LAYER2/NR_MAC_gNB/mac_proto.h"
//#include "openair2/LAYER2/NR_MAC_UE/mac_proto.h"
58
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
59
#include "NR_asn_constant.h"
60
#include "RRC/NR/MESSAGES/asn1_msg.h"
61 62 63
#include "openair1/SIMULATION/RF/rf.h"
#include "openair1/SIMULATION/TOOLS/sim.h"
#include "openair1/SIMULATION/NR_PHY/nr_unitary_defs.h"
Raymond Knopp's avatar
Raymond Knopp committed
64
//#include "openair1/SIMULATION/NR_PHY/nr_dummy_functions.c"
65

Raymond Knopp's avatar
Raymond Knopp committed
66
#include "NR_RRCReconfiguration.h"
67 68 69 70
#define inMicroS(a) (((double)(a))/(cpu_freq_GHz*1000.0))
#include "SIMULATION/LTE_PHY/common_sim.h"


Raymond Knopp's avatar
Raymond Knopp committed
71

72 73 74
PHY_VARS_gNB *gNB;
PHY_VARS_NR_UE *UE;
RAN_CONTEXT_t RC;
75 76
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];

77
double cpuf;
78

Raymond Knopp's avatar
Raymond Knopp committed
79
int sf_ahead=4;
80 81

// dummy functions
Raymond Knopp's avatar
Raymond Knopp committed
82 83 84 85
int dummy_nr_ue_ul_indication(nr_uplink_indication_t *ul_info)              { return(0);  }

void pdcp_run (const protocol_ctxt_t *const  ctxt_pP) { return;}

86 87 88 89 90 91 92 93 94
int nfapi_mode=0;


int8_t nr_mac_rrc_data_ind_ue(const module_id_t     module_id,
			      const int             CC_id,
			      const uint8_t         gNB_index,
			      const int8_t          channel,
			      const uint8_t*        pduP,
			      const sdu_size_t      pdu_len)
95 96 97 98 99
{
  return 0;
}


yilmazt's avatar
yilmazt committed
100
uint16_t NB_UE_INST = 1;
101

102
//Dummy Functions
103 104
//lte_subframe_t subframe_select(LTE_DL_FRAME_PARMS *frame_parms, unsigned char subframe) {return(SF_DL);}
int rlc_module_init (int eNB_id) {return(0);}
105

106

107 108 109
void pdcp_layer_init(void) {}
int rrc_init_nr_global_param(void){return(0);}

110 111
void config_common(int Mod_idP,
                   int pdsch_AntennaPorts, 
112
		   NR_ServingCellConfigCommon_t *scc
Raymond Knopp's avatar
Raymond Knopp committed
113
		   );
114

115
uint64_t get_softmodem_optmask(void) {return 0;}
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
mac_rlc_status_resp_t mac_rlc_status_ind(const module_id_t       module_idP,
                                         const rnti_t            rntiP,
                                         const eNB_index_t       eNB_index,
                                         const frame_t           frameP,
                                         const sub_frame_t       subframeP,
                                         const eNB_flag_t        enb_flagP,
                                         const MBMS_flag_t       MBMS_flagP,
                                         const logical_chan_id_t channel_idP,
                                         const tb_size_t         tb_sizeP,
                                         const uint32_t          sourceL2Id,
                                         const uint32_t          destinationL2Id) {mac_rlc_status_resp_t  mac_rlc_status_resp = {0}; return mac_rlc_status_resp;}
tbs_size_t mac_rlc_data_req(const module_id_t       module_idP,
                            const rnti_t            rntiP,
                            const eNB_index_t       eNB_index,
                            const frame_t           frameP,
                            const eNB_flag_t        enb_flagP,
                            const MBMS_flag_t       MBMS_flagP,
                            const logical_chan_id_t channel_idP,
                            const tb_size_t         tb_sizeP,
                            char                    *buffer_pP,
                            const uint32_t          sourceL2Id,
                            const uint32_t          destinationL2Id) {return 0;}
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
int generate_dlsch_header(unsigned char *mac_header,
                          unsigned char num_sdus,
                          unsigned short *sdu_lengths,
                          unsigned char *sdu_lcids,
                          unsigned char drx_cmd,
                          unsigned short timing_advance_cmd,
                          unsigned char *ue_cont_res_id,
                          unsigned char short_padding,
                          unsigned short post_padding){return 0;}
void nr_ip_over_LTE_DRB_preconfiguration(void){}
void mac_rlc_data_ind     (
  const module_id_t         module_idP,
  const rnti_t              rntiP,
  const eNB_index_t         eNB_index,
  const frame_t             frameP,
  const eNB_flag_t          enb_flagP,
  const MBMS_flag_t         MBMS_flagP,
  const logical_chan_id_t   channel_idP,
  char                     *buffer_pP,
  const tb_size_t           tb_sizeP,
  num_tb_t                  num_tbP,
  crc_t                    *crcs_pP)
{}
161

162
// needed for some functions
163
openair0_config_t openair0_cfg[MAX_CARDS];
164

165

166 167 168
int main(int argc, char **argv)
{
  char c;
169
  int i,aa;//,l;
170
  double sigma2, sigma2_dB=10, SNR, snr0=-2.0, snr1=2.0;
171 172 173
  uint8_t snr1set=0;
  int **txdata;
  double **s_re,**s_im,**r_re,**r_im;
174 175
  //double iqim = 0.0;
  //unsigned char pbch_pdu[6];
176 177 178
  //  int sync_pos, sync_pos_slot;
  //  FILE *rx_frame_file;
  FILE *output_fd = NULL;
179
  //uint8_t write_output_file=0;
180
  //int result;
181
  //int freq_offset;
182
  //  int subframe_offset;
183
  //  char fname[40], vname[40];
Ahmed Hussein's avatar
Ahmed Hussein committed
184
  int trial, n_trials = 1, n_errors = 0, n_false_positive = 0;
185
  //int n_errors2, n_alamouti;
186 187 188
  uint8_t transmission_mode = 1,n_tx=1,n_rx=1;

  channel_desc_t *gNB2UE;
189 190 191
  //uint32_t nsymb,tx_lev,tx_lev1 = 0,tx_lev2 = 0;
  //uint8_t extended_prefix_flag=0;
  //int8_t interf1=-21,interf2=-21;
192 193

  FILE *input_fd=NULL,*pbch_file_fd=NULL;
194
  //char input_val_str[50],input_val_str2[50];
195

196
  //uint8_t frame_mod4,num_pdcch_symbols = 0;
197 198 199

  SCM_t channel_model=AWGN;//Rayleigh1_anticorr;

200 201
  //double pbch_sinr;
  //int pbch_tx_ant;
Ahmed Hussein's avatar
Ahmed Hussein committed
202
  int N_RB_DL=106,mu=1;
203
  nfapi_nr_dl_tti_pdsch_pdu_rel15_t dlsch_config;
204

205
  //unsigned char frame_type = 0;
206

207
  int frame=0,slot=1;
208 209 210 211 212 213 214
  int frame_length_complex_samples;
  int frame_length_complex_samples_no_prefix;
  NR_DL_FRAME_PARMS *frame_parms;
  UE_nr_rxtx_proc_t UE_proc;
  NR_Sched_Rsp_t Sched_INFO;
  gNB_MAC_INST *gNB_mac;
  NR_UE_MAC_INST_t *UE_mac;
215
  int cyclic_prefix_type = NFAPI_CP_NORMAL;
216 217 218
  int run_initial_sync=0;
  int do_pdcch_flag=1;

Raymond Knopp's avatar
Raymond Knopp committed
219
  int loglvl=OAILOG_INFO;
220 221

  float target_error_rate = 0.01;
222
  int css_flag=0;
223 224 225

  cpuf = get_cpu_freq_GHz();

226
  if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == 0) {
yilmazt's avatar
yilmazt committed
227
    exit_fun("[NR_DLSIM] Error, configuration module init failed\n");
228 229 230 231
  }

  randominit(0);

232
  int mcsIndex_set=0,rbStart_set=0,rbSize_set=0;
233
  int print_perf             = 0;
234

235
  while ((c = getopt (argc, argv, "f:hA:pf:g:i:j:n:s:S:t:x:y:z:M:N:F:GR:dPIL:Ea:b:e:m:")) != -1) {
236
    switch (c) {
237
    /*case 'f':
238 239 240 241 242 243 244
      write_output_file=1;
      output_fd = fopen(optarg,"w");

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

247
    /*case 'd':
248
      frame_type = 1;
249
      break;*/
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

    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:
282
        printf("Unsupported channel model!\n");
283 284 285 286 287
        exit(-1);
      }

      break;

288
    /*case 'i':
289 290 291 292 293
      interf1=atoi(optarg);
      break;

    case 'j':
      interf2=atoi(optarg);
294
      break;*/
295 296 297 298 299 300 301

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

    case 's':
      snr0 = atof(optarg);
302
      printf("Setting SNR0 to %f\n",snr0);
303 304 305 306 307
      break;

    case 'S':
      snr1 = atof(optarg);
      snr1set=1;
308
      printf("Setting SNR1 to %f\n",snr1);
309 310 311 312 313 314 315
      break;

      /*
      case 't':
      Td= atof(optarg);
      break;
      */
316
    /*case 'p':
317
      extended_prefix_flag=1;
318
      break;*/
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334

      /*
      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);

      if ((transmission_mode!=1) &&
          (transmission_mode!=2) &&
          (transmission_mode!=6)) {
335
        printf("Unsupported transmission mode %d\n",transmission_mode);
336 337 338 339 340 341 342 343 344
        exit(-1);
      }

      break;

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

      if ((n_tx==0) || (n_tx>2)) {
345
        printf("Unsupported number of tx antennas %d\n",n_tx);
346 347 348 349 350 351 352 353 354
        exit(-1);
      }

      break;

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

      if ((n_rx==0) || (n_rx>2)) {
355
        printf("Unsupported number of rx antennas %d\n",n_rx);
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
        exit(-1);
      }

      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 'P':
376 377
      print_perf=1;
      opp_enabled=1;
378 379 380 381 382
      break;
      
    case 'I':
      run_initial_sync=1;
      target_error_rate=0.1;
383
      slot = 0;
384 385 386 387 388 389
      break;

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

390

391 392 393
    case 'E':
	css_flag=1;
	break;
394

395

396
    case 'a':
Raymond Knopp's avatar
Raymond Knopp committed
397
      dlsch_config.rbStart = atoi(optarg);
398
      rbStart_set=1;
399 400 401
      break;

    case 'b':
Raymond Knopp's avatar
Raymond Knopp committed
402
      dlsch_config.rbSize = atoi(optarg);
403
      rbSize_set=1;
404 405 406
      break;

    case 'e':
Raymond Knopp's avatar
Raymond Knopp committed
407
      dlsch_config.mcsIndex[0] = atoi(optarg);
408
      mcsIndex_set=1;
409 410
      break;

411 412 413
    case 'm':
      mu = atoi(optarg);
      break;
414

415 416 417 418 419
    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");
420 421
      //printf("-p Use extended prefix mode\n");
      //printf("-d Use TDD\n");
422 423 424 425 426
      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");
427
      printf("-y Number of TX antennas used in gNB\n");
428
      printf("-z Number of RX antennas used in UE\n");
429 430
      //printf("-i Relative strength of first intefering gNB (in dB) - cell_id mod 3 = 1\n");
      //printf("-j Relative strength of second intefering gNB (in dB) - cell_id mod 3 = 2\n");
431 432 433
      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");
434 435
      //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");
436
      printf("-F Input filename (.txt format) for RX conformance testing\n");
437
      printf("-E used CSS scheduler\n");
438
      printf("-o CORESET offset\n");
439 440
      printf("-a Start PRB for PDSCH\n");
      printf("-b Number of PRB for PDSCH\n");
441 442
      printf("-c Start symbol for PDSCH (fixed for now)\n");
      printf("-j Number of symbols for PDSCH (fixed for now)\n");
443
      printf("-e MSC index\n");
444 445 446 447
      exit (-1);
      break;
    }
  }
Raymond Knopp's avatar
Raymond Knopp committed
448
  
449 450 451 452 453 454 455 456
  logInit();
  set_glog(loglvl);
  T_stdout = 1;

  if (snr1set==0)
    snr1 = snr0+10;


457 458 459
  RC.gNB = (PHY_VARS_gNB**) malloc(sizeof(PHY_VARS_gNB *));
  RC.gNB[0] = (PHY_VARS_gNB*) malloc(sizeof(PHY_VARS_gNB ));
  memset(RC.gNB[0],0,sizeof(PHY_VARS_gNB));
Raymond Knopp's avatar
Raymond Knopp committed
460

461
  gNB = RC.gNB[0];
462 463 464 465 466 467
  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;

Raymond Knopp's avatar
Raymond Knopp committed
468 469 470 471
  RC.nb_nr_macrlc_inst = 1;
  mac_top_init_gNB();
  gNB_mac = RC.nrmac[0];
  gNB_RRC_INST rrc;
Raymond Knopp's avatar
Raymond Knopp committed
472
  memset((void*)&rrc,0,sizeof(rrc));
Raymond Knopp's avatar
Raymond Knopp committed
473
  // read in SCGroupConfig
Raymond Knopp's avatar
Raymond Knopp committed
474 475
  FILE *scg_fd = fopen("reconfig.raw","r");
  AssertFatal(scg_fd != NULL,"no reconfig.raw file\n");
Raymond Knopp's avatar
Raymond Knopp committed
476 477 478 479
  char buffer[1024];
  int msg_len=fread(buffer,1,1024,scg_fd);
  NR_RRCReconfiguration_t *NR_RRCReconfiguration;

Raymond Knopp's avatar
Raymond Knopp committed
480
  printf("Decoding NR_RRCReconfiguration (%d bytes)\n",msg_len);
Raymond Knopp's avatar
Raymond Knopp committed
481 482 483 484 485 486 487 488 489 490 491 492 493 494
  asn_dec_rval_t dec_rval = uper_decode_complete( NULL,
						  &asn_DEF_NR_RRCReconfiguration,
						  (void **)&NR_RRCReconfiguration,
						  (uint8_t *)buffer,
						  msg_len); 
  
  if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
    AssertFatal(1==0,"NR_RRCReConfiguration decode error\n");
    // free the memory
    SEQUENCE_free( &asn_DEF_NR_RRCReconfiguration, NR_RRCReconfiguration, 1 );
    exit(-1);
  }      
  fclose(scg_fd);

Raymond Knopp's avatar
Raymond Knopp committed
495 496
  AssertFatal(NR_RRCReconfiguration->criticalExtensions.present == NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration,"wrong NR_RRCReconfiguration->criticalExstions.present type\n");

Raymond Knopp's avatar
Raymond Knopp committed
497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
  NR_RRCReconfiguration_IEs_t *reconfig_ies = NR_RRCReconfiguration->criticalExtensions.choice.rrcReconfiguration;
  NR_CellGroupConfig_t *secondaryCellGroup;
  dec_rval = uper_decode_complete( NULL,
				   &asn_DEF_NR_CellGroupConfig,
				   (void **)&secondaryCellGroup,
				   (uint8_t *)reconfig_ies->secondaryCellGroup->buf,
				   reconfig_ies->secondaryCellGroup->size); 
  
  if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
    AssertFatal(1==0,"NR_CellGroupConfig decode error\n");
    // free the memory
    SEQUENCE_free( &asn_DEF_NR_CellGroupConfig, secondaryCellGroup, 1 );
    exit(-1);
  }      

  NR_ServingCellConfigCommon_t *scc = secondaryCellGroup->spCellConfig->reconfigurationWithSync->spCellConfigCommon;
  
Raymond Knopp's avatar
Raymond Knopp committed
514
  xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup);
Raymond Knopp's avatar
Raymond Knopp committed
515

Raymond Knopp's avatar
Raymond Knopp committed
516 517 518 519
  rrc.carrier.servingcellconfigcommon = secondaryCellGroup->spCellConfig->reconfigurationWithSync->spCellConfigCommon;
  printf("%p,%p\n",
	 secondaryCellGroup->spCellConfig->reconfigurationWithSync->spCellConfigCommon,
	 rrc.carrier.servingcellconfigcommon);
Raymond Knopp's avatar
Raymond Knopp committed
520

Raymond Knopp's avatar
Raymond Knopp committed
521 522
  AssertFatal((gNB->if_inst         = NR_IF_Module_init(0))!=NULL,"Cannot register interface");
  gNB->if_inst->NR_PHY_config_req      = nr_phy_config_request;
Raymond Knopp's avatar
Raymond Knopp committed
523
  // common configuration
524
  rrc_mac_config_req_gNB(0,0,1,scc,0,0,NULL);
Raymond Knopp's avatar
Raymond Knopp committed
525
  // UE dedicated configuration
526
  rrc_mac_config_req_gNB(0,0,1,NULL,1,secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity,secondaryCellGroup);
Raymond Knopp's avatar
Raymond Knopp committed
527
  phy_init_nr_gNB(gNB,0,0);
528
  N_RB_DL = gNB->frame_parms.N_RB_DL;
Raymond Knopp's avatar
Raymond Knopp committed
529
  // stub to configure frame_parms
Raymond Knopp's avatar
Raymond Knopp committed
530
  //  nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions);
Raymond Knopp's avatar
Raymond Knopp committed
531 532 533
  // call MAC to configure common parameters


534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551
  double fs,bw;

  if (mu == 1 && N_RB_DL == 217) { 
    fs = 122.88e6;
    bw = 80e6;
  }					       
  else if (mu == 1 && N_RB_DL == 245) {
    fs = 122.88e6;
    bw = 90e6;
  }
  else if (mu == 1 && N_RB_DL == 273) {
    fs = 122.88e6;
    bw = 100e6;
  }
  else if (mu == 1 && N_RB_DL == 106) { 
    fs = 61.44e6;
    bw = 40e6;
  }
552 553 554 555
  else if (mu == 3 && N_RB_DL == 66) {
    fs = 122.88e6;
    bw = 100e6;
  }
556 557 558 559
  else if (mu == 3 && N_RB_DL == 32) {
    fs = 61.44e6;
    bw = 50e6;
  }
560 561 562 563 564
  else AssertFatal(1==0,"Unsupported numerology for mu %d, N_RB %d\n",mu, N_RB_DL);

  gNB2UE = new_channel_desc_scm(n_tx,
                                n_rx,
                                channel_model,
565 566
 				fs,
				bw,
567 568 569 570 571
                                0,
                                0,
                                0);

  if (gNB2UE==NULL) {
572
    printf("Problem generating channel model. Exiting.\n");
573 574 575 576
    exit(-1);
  }

  frame_length_complex_samples = frame_parms->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
577
  frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598

  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*));

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

    printf("Allocating %d samples for txdata\n",frame_length_complex_samples);
    txdata[i] = malloc(frame_length_complex_samples*sizeof(int));
599
    bzero(txdata[i],frame_length_complex_samples*sizeof(int));
600 601 602 603 604 605 606 607 608 609
  
  }

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


  //configure UE
  UE = malloc(sizeof(PHY_VARS_NR_UE));
Raymond Knopp's avatar
Raymond Knopp committed
610
  memset((void*)UE,0,sizeof(PHY_VARS_NR_UE));
611 612 613 614
  PHY_vars_UE_g = malloc(sizeof(PHY_VARS_NR_UE**));
  PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_NR_UE*));
  PHY_vars_UE_g[0][0] = UE;
  memcpy(&UE->frame_parms,frame_parms,sizeof(NR_DL_FRAME_PARMS));
Raymond Knopp's avatar
Raymond Knopp committed
615

616
  if (run_initial_sync==1)  UE->is_synchronized = 0;
617
  else                      {UE->is_synchronized = 1; UE->UE_mode[0]=PUSCH;}
618 619
                      
  UE->perfect_ce = 0;
620
  for (i=0;i<10;i++) UE->current_thread_id[i] = 0;
621 622 623 624 625 626 627

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

628 629
  init_nr_ue_transport(UE,0);

630
  nr_gold_pbch(UE);
631
  nr_gold_pdcch(UE,0,2);
632

633
   
634
  nr_l2_init_ue(NULL);
635
  UE_mac = get_mac_inst(0);
Guy De Souza's avatar
Guy De Souza committed
636
  
637 638 639
  UE->if_inst = nr_ue_if_module_init(0);
  UE->if_inst->scheduled_response = nr_ue_scheduled_response;
  UE->if_inst->phy_config_request = nr_ue_phy_config_request;
640
  UE->if_inst->dl_indication = nr_ue_dl_indication;
641 642 643
  UE->if_inst->ul_indication = dummy_nr_ue_ul_indication;
  

644
  UE_mac->if_module = nr_ue_if_module_init(0);
Ahmed Hussein's avatar
Ahmed Hussein committed
645
  
646
  unsigned int available_bits=0;
Ahmed Hussein's avatar
Ahmed Hussein committed
647 648 649 650 651
  unsigned char *estimated_output_bit;
  unsigned char *test_input_bit;
  unsigned int errors_bit    = 0;
  uint32_t errors_scrambling = 0;

652

Ahmed Hussein's avatar
Ahmed Hussein committed
653 654
  test_input_bit       = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384);
  estimated_output_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384);
655 656
  
  // generate signal
657 658 659 660 661 662 663
  AssertFatal(input_fd==NULL,"Not ready for input signal file\n");
  gNB->pbch_configured = 1;
  gNB->ssb_pdu.ssb_pdu_rel15.bchPayload=0x001234;
  
  if (mcsIndex_set==0) dlsch_config.mcsIndex[0]=9;
  if (rbSize_set==0) dlsch_config.rbSize=N_RB_DL;
  if (rbStart_set==0) dlsch_config.rbStart=0;
664

Raymond Knopp's avatar
Raymond Knopp committed
665

666
  //Configure UE
667 668
  rrc.carrier.MIB = (uint8_t*) malloc(4);
  rrc.carrier.sizeof_MIB = do_MIB_NR(&rrc,0);
669

670
  nr_rrc_mac_config_req_ue(0,0,0,rrc.carrier.mib.message.choice.mib,secondaryCellGroup->spCellConfig);
671

672 673 674 675 676 677 678 679

  nr_dcireq_t dcireq;
  nr_scheduled_response_t scheduled_response;
  memset((void*)&dcireq,0,sizeof(dcireq));
  memset((void*)&scheduled_response,0,sizeof(scheduled_response));
  dcireq.module_id = 0;
  dcireq.gNB_index = 0;
  dcireq.cc_id     = 0;
680
  
681 682 683 684 685 686 687
  scheduled_response.dl_config = &dcireq.dl_config_req;
  scheduled_response.ul_config = &dcireq.ul_config_req;
  scheduled_response.tx_request = NULL;
  scheduled_response.module_id = 0;
  scheduled_response.CC_id     = 0;
  scheduled_response.frame = frame;
  scheduled_response.slot  = slot;
688
  
Francesco Mani's avatar
Francesco Mani committed
689

690 691
  nr_ue_phy_config_request(&UE_mac->phy_config);

Ahmed Hussein's avatar
Ahmed Hussein committed
692
  for (SNR = snr0; SNR < snr1; SNR += .2) {
693

694 695 696 697 698 699 700 701 702 703 704 705 706
    varArray_t *table_tx=initVarArray(1000,sizeof(double));
    reset_meas(&gNB->phy_proc_tx); // total gNB tx
    reset_meas(&gNB->dlsch_scrambling_stats);
    reset_meas(&gNB->dlsch_interleaving_stats);
    reset_meas(&gNB->dlsch_rate_matching_stats);
    reset_meas(&gNB->dlsch_segmentation_stats);
    reset_meas(&gNB->dlsch_modulation_stats);
    reset_meas(&gNB->dlsch_encoding_stats);
    reset_meas(&gNB->tinput);
    reset_meas(&gNB->tprep);
    reset_meas(&gNB->tparity);
    reset_meas(&gNB->toutput);  

707
    n_errors = 0;
708 709
    //n_errors2 = 0;
    //n_alamouti = 0;
710
    errors_scrambling=0;
711
    n_false_positive = 0;
Ahmed Hussein's avatar
Ahmed Hussein committed
712
    for (trial = 0; trial < n_trials; trial++) {
713

714
      errors_bit = 0;
Ahmed Hussein's avatar
Ahmed Hussein committed
715
      //multipath channel
716
      //multipath_channel(gNB2UE,s_re,s_im,r_re,r_im,frame_length_complex_samples,0);
717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777

      memset(RC.nrmac[0]->cce_list[1][0],0,MAX_NUM_CCE*sizeof(int));
      clear_nr_nfapi_information(RC.nrmac[0], 0, frame, slot);
      if (css_flag == 0) nr_schedule_uss_dlsch_phytest(0,frame,slot,&dlsch_config);
      else               nr_schedule_css_dlsch_phytest(0,frame,slot);
      
      
      Sched_INFO.module_id = 0;
      Sched_INFO.CC_id     = 0;
      Sched_INFO.frame     = frame;
      Sched_INFO.slot      = slot;
      Sched_INFO.DL_req    = &gNB_mac->DL_req[0];
      Sched_INFO.UL_tti_req    = &gNB_mac->UL_tti_req[0];
      Sched_INFO.UL_dci_req  = NULL;
      Sched_INFO.TX_req    = &gNB_mac->TX_req[0];
      nr_schedule_response(&Sched_INFO);
      
      phy_procedures_gNB_TX(gNB,frame,slot,0);
          
      //nr_common_signal_procedures (gNB,frame,subframe);
      int txdataF_offset = (slot%2) * frame_parms->samples_per_slot_wCP;
      
      if (n_trials==1) {
	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);
      }
      int tx_offset = slot*frame_parms->samples_per_slot;
      if (n_trials==1) printf("samples_per_slot_wCP = %d\n", frame_parms->samples_per_slot_wCP);
      
      //TODO: loop over slots
      for (aa=0; aa<gNB->frame_parms.nb_antennas_tx; aa++) {
	
	if (cyclic_prefix_type == 1) {
	  PHY_ofdm_mod(&gNB->common_vars.txdataF[aa][txdataF_offset],
		       &txdata[aa][tx_offset],
		       frame_parms->ofdm_symbol_size,
		       12,
		       frame_parms->nb_prefix_samples,
		       CYCLIC_PREFIX);
	} else {
	  nr_normal_prefix_mod(&gNB->common_vars.txdataF[aa][txdataF_offset],
			       &txdata[aa][tx_offset],
			       14,
			       frame_parms);
	}
      }
     
      if (n_trials==1) {
	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);
      }
      if (output_fd) 
	fwrite(txdata[0],sizeof(int32_t),frame_length_complex_samples,output_fd);
      
      int txlev = signal_energy(&txdata[0][(slot*frame_parms->samples_per_slot)+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);
      
      //  if (n_trials==1) printf("txlev %d (%f)\n",txlev,10*log10((double)txlev));
      
778 779 780
      for (i=(slot * frame_parms->samples_per_slot); 
	   i<((slot+1) * frame_parms->samples_per_slot); 
	   i++) {
781 782 783 784 785 786 787 788
	for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
	  r_re[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)]);
	  r_im[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)+1]);
	}
      }
      
      NR_gNB_DLSCH_t *gNB_dlsch = gNB->dlsch[0][0];
      nfapi_nr_dl_tti_pdsch_pdu_rel15_t rel15 = gNB_dlsch->harq_processes[0]->pdsch_pdu.pdsch_pdu_rel15;
789 790
      
      //AWGN
791
      sigma2_dB = 10 * log10((double)txlev * ((double)UE->frame_parms.ofdm_symbol_size/(12*rel15.rbSize))) - SNR;
Ahmed Hussein's avatar
Ahmed Hussein committed
792
      sigma2    = pow(10, sigma2_dB/10);
793
      if (n_trials==1) printf("sigma2 %f (%f dB), txlev %f (factor %f)\n",sigma2,sigma2_dB,10*log10((double)txlev),(double)(double)UE->frame_parms.ofdm_symbol_size/(12*rel15.rbSize));
794
      
795 796 797
      for (i=(slot * frame_parms->samples_per_slot); 
	   i<((slot+1) * frame_parms->samples_per_slot); 
	   i++) {
798 799 800 801 802
	for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
	  ((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)));
	}
      }
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
      
      UE->rx_offset=0;
      UE_proc.frame_rx = frame;
      UE_proc.nr_tti_rx= slot;
      UE_proc.subframe_rx = slot;
      
      dcireq.frame     = frame;
      dcireq.slot      = slot;
      
      nr_ue_dcireq(&dcireq); //to be replaced with function pointer later
      nr_ue_scheduled_response(&scheduled_response);
      
      phy_procedures_nrUE_RX(UE,
			     &UE_proc,
			     0,
			     do_pdcch_flag,
			     normal_txrx);
      
      if (UE->dlsch[UE->current_thread_id[slot]][0][0]->last_iteration_cnt >= 
	  UE->dlsch[UE->current_thread_id[slot]][0][0]->max_ldpc_iterations+1)
	n_errors++;
      
      //----------------------------------------------------------
      //---------------------- count errors ----------------------
      //----------------------------------------------------------
      
      
      
      NR_UE_DLSCH_t *dlsch0 = UE->dlsch[UE->current_thread_id[UE_proc.nr_tti_rx]][0][0];
      
      int harq_pid = dlsch0->current_harq_pid;
      NR_DL_UE_HARQ_t *UE_harq_process = dlsch0->harq_processes[harq_pid];
      
      NR_UE_PDSCH **pdsch_vars = UE->pdsch_vars[UE->current_thread_id[UE_proc.nr_tti_rx]];
      int16_t *UE_llr = pdsch_vars[0]->llr[0];
      
      
      uint32_t TBS         = rel15.TBSize[0];
      uint16_t length_dmrs = 1;
      uint16_t nb_rb       = rel15.rbSize;
      uint8_t  nb_re_dmrs  = rel15.dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6 : 4;
      uint8_t  mod_order   = rel15.qamModOrder[0];
      uint8_t  nb_symb_sch = rel15.NrOfSymbols;
      
      available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, mod_order, rel15.nrOfLayers);
      
      for (i = 0; i < available_bits; i++) {
Raymond Knopp's avatar
Raymond Knopp committed
850
	
851 852 853 854 855 856
	if(((gNB_dlsch->harq_processes[harq_pid]->f[i] == 0) && (UE_llr[i] <= 0)) || 
	   ((gNB_dlsch->harq_processes[harq_pid]->f[i] == 1) && (UE_llr[i] >= 0)))
	  {
	    if(errors_scrambling == 0) {
	      LOG_D(PHY,"\n");
	      LOG_D(PHY,"First bit in error in unscrambling = %d\n",i);
Raymond Knopp's avatar
Raymond Knopp committed
857
	    }
858
	    errors_scrambling++;
Raymond Knopp's avatar
Raymond Knopp committed
859 860
	  }
	
861 862
      }
      for (i = 0; i < TBS; i++) {
Raymond Knopp's avatar
Raymond Knopp committed
863
	
864 865
	estimated_output_bit[i] = (UE_harq_process->b[i/8] & (1 << (i & 7))) >> (i & 7);
	test_input_bit[i]       = (gNB_dlsch->harq_processes[harq_pid]->b[i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments
Raymond Knopp's avatar
Raymond Knopp committed
866
	
867 868 869 870
	if (estimated_output_bit[i] != test_input_bit[i]) {
	  if(errors_bit == 0)
	    LOG_D(PHY,"First bit in error in decoding = %d (errors scrambling %d)\n",i,errors_scrambling);
	  errors_bit++;
Raymond Knopp's avatar
Raymond Knopp committed
871 872
	}
	
873 874 875 876 877 878
      }
      
      ////////////////////////////////////////////////////////////
      
      if (errors_scrambling > 0) {
	if (n_trials == 1)
879
	  printf("errors_scrambling = %d/%d (trial %d)\n", errors_scrambling, available_bits,trial);
880 881 882 883 884 885 886
      }
      
      if (errors_bit > 0) {
	n_false_positive++;
	if (n_trials == 1)
	  printf("errors_bit = %u (trial %d)\n", errors_bit, trial);
      }
Raymond Knopp's avatar
Raymond Knopp committed
887
      
Ahmed Hussein's avatar
Ahmed Hussein committed
888
    } // noise trials
889

Ahmed Hussein's avatar
Ahmed Hussein committed
890 891
    printf("*****************************************\n");
    printf("SNR %f, (false positive %f)\n", SNR,
Sakthivel Velumani's avatar
Sakthivel Velumani committed
892
           (float) n_errors / (float) n_trials);
Ahmed Hussein's avatar
Ahmed Hussein committed
893 894
    printf("*****************************************\n");
    printf("\n");
895
    printf("SNR %f : n_errors (negative CRC) = %d/%d, Channel BER %e\n", SNR, n_errors, n_trials,(double)errors_scrambling/available_bits/n_trials);
Ahmed Hussein's avatar
Ahmed Hussein committed
896
    printf("\n");
897

898 899 900 901 902 903 904 905 906 907
    if (n_trials == 1) {
      
      LOG_M("rxsig0.m","rxs0", UE->common_vars.rxdata[0], frame_length_complex_samples, 1, 1);
      if (UE->frame_parms.nb_antennas_rx>1)
	LOG_M("rxsig1.m","rxs1", UE->common_vars.rxdata[1], frame_length_complex_samples, 1, 1);
      LOG_M("chestF0.m","chF0",UE->pdsch_vars[0][0]->dl_ch_estimates_ext,N_RB_DL*12*14,1,1);
      write_output("rxF_comp.m","rxFc",&UE->pdsch_vars[0][0]->rxdataF_comp0[0][0],N_RB_DL*12*14,1,1);
      break;
    }

908
    if ((float)n_errors/(float)n_trials <= target_error_rate) {
Sakthivel Velumani's avatar
Sakthivel Velumani committed
909
      printf("PDSCH test OK\n");
910 911 912
      break;
    }

913 914

    if (print_perf==1) {
915 916 917 918 919
      printf("\ngNB TX function statistics (per %d us slot, NPRB %d, mcs %d, TBS %d, Kr %d (Zc %d))\n",
	     1000>>*scc->ssbSubcarrierSpacing,dlsch_config.rbSize,dlsch_config.mcsIndex[0],
	     gNB->dlsch[0][0]->harq_processes[0]->pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3,
	     gNB->dlsch[0][0]->harq_processes[0]->K,
	     gNB->dlsch[0][0]->harq_processes[0]->K/((gNB->dlsch[0][0]->harq_processes[0]->pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3)>3824?22:10));
920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963
      printDistribution(&gNB->phy_proc_tx,table_tx,"PHY proc tx");
      printStatIndent2(&gNB->dlsch_encoding_stats,"DLSCH encoding time");
      printStatIndent3(&gNB->dlsch_segmentation_stats,"DLSCH segmentation time");
      printStatIndent3(&gNB->tinput,"DLSCH LDPC input processing time");
      printStatIndent3(&gNB->tprep,"DLSCH LDPC input preparation time");
      printStatIndent3(&gNB->tparity,"DLSCH LDPC parity generation time");
      printStatIndent3(&gNB->toutput,"DLSCH LDPC output generation time");
      printStatIndent3(&gNB->dlsch_rate_matching_stats,"DLSCH Rate Mataching time");
      printStatIndent3(&gNB->dlsch_interleaving_stats,  "DLSCH Interleaving time");
      printStatIndent2(&gNB->dlsch_modulation_stats,"DLSCH modulation time");
      printStatIndent2(&gNB->dlsch_scrambling_stats,  "DLSCH scrambling time");


      printf("\nUE RX function statistics (per %d us slot)\n",1000>>*scc->ssbSubcarrierSpacing);
      /*
      printDistribution(&phy_proc_rx_tot, table_rx,"Total PHY proc rx");
      printStatIndent(&ue_front_end_tot,"Front end processing");
      printStatIndent(&dlsch_llr_tot,"rx_pdsch processing");
      printStatIndent2(&pdsch_procedures_tot,"pdsch processing");
      printStatIndent2(&dlsch_procedures_tot,"dlsch processing");
      printStatIndent2(&UE->crnti_procedures_stats,"C-RNTI processing");
      printStatIndent(&UE->ofdm_demod_stats,"ofdm demodulation");
      printStatIndent(&UE->dlsch_channel_estimation_stats,"DLSCH channel estimation time");
      printStatIndent(&UE->dlsch_freq_offset_estimation_stats,"DLSCH frequency offset estimation time");
      printStatIndent(&dlsch_decoding_tot, "DLSCH Decoding time ");
      printStatIndent(&UE->dlsch_unscrambling_stats,"DLSCH unscrambling time");
      printStatIndent(&UE->dlsch_rate_unmatching_stats,"DLSCH Rate Unmatching");
      printf("|__ DLSCH Turbo Decoding(%d bits), avg iterations: %.1f       %.2f us (%d cycles, %d trials)\n",
	     UE->dlsch[UE->current_thread_id[subframe]][0][0]->harq_processes[0]->Cminus ?
	     UE->dlsch[UE->current_thread_id[subframe]][0][0]->harq_processes[0]->Kminus :
	     UE->dlsch[UE->current_thread_id[subframe]][0][0]->harq_processes[0]->Kplus,
	     UE->dlsch_tc_intl1_stats.trials/(double)UE->dlsch_tc_init_stats.trials,
	     (double)UE->dlsch_turbo_decoding_stats.diff/UE->dlsch_turbo_decoding_stats.trials*timeBase,
	     (int)((double)UE->dlsch_turbo_decoding_stats.diff/UE->dlsch_turbo_decoding_stats.trials),
	     UE->dlsch_turbo_decoding_stats.trials);
      printStatIndent2(&UE->dlsch_tc_init_stats,"init");
      printStatIndent2(&UE->dlsch_tc_alpha_stats,"alpha");
      printStatIndent2(&UE->dlsch_tc_beta_stats,"beta");
      printStatIndent2(&UE->dlsch_tc_gamma_stats,"gamma");
      printStatIndent2(&UE->dlsch_tc_ext_stats,"ext");
      printStatIndent2(&UE->dlsch_tc_intl1_stats,"turbo internal interleaver");
      printStatIndent2(&UE->dlsch_tc_intl2_stats,"intl2+HardDecode+CRC");
      */
    }
964 965
  } // NSR

Ahmed Hussein's avatar
Ahmed Hussein committed
966
  for (i = 0; i < 2; i++) {
967 968 969 970 971 972 973 974 975 976 977 978
    free(s_re[i]);
    free(s_im[i]);
    free(r_re[i]);
    free(r_im[i]);
    free(txdata[i]);
  }

  free(s_re);
  free(s_im);
  free(r_re);
  free(r_im);
  free(txdata);
Ahmed Hussein's avatar
Ahmed Hussein committed
979 980 981
  free(test_input_bit);
  free(estimated_output_bit);
  
982 983 984 985 986 987 988
  if (output_fd)
    fclose(output_fd);

  if (input_fd)
    fclose(input_fd);

  return(n_errors);
Raymond Knopp's avatar
Raymond Knopp committed
989
  
990
}