dlsim.c 32.9 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

206
  //unsigned char frame_type = 0;
207

208
  int frame=0,slot=1;
209 210 211 212 213 214 215
  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;
216
  int cyclic_prefix_type = NFAPI_CP_NORMAL;
217 218 219
  int run_initial_sync=0;
  int do_pdcch_flag=1;

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

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

  cpuf = get_cpu_freq_GHz();

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

  randominit(0);

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

236
  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:")) != -1) {
237
    switch (c) {
238
    /*case 'f':
239 240 241 242 243 244 245
      write_output_file=1;
      output_fd = fopen(optarg,"w");

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

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

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

      break;

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

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

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

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

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

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

      /*
      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)) {
336
        printf("Unsupported transmission mode %d\n",transmission_mode);
337 338 339 340 341 342 343 344 345
        exit(-1);
      }

      break;

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

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

      break;

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

      if ((n_rx==0) || (n_rx>2)) {
356
        printf("Unsupported number of rx antennas %d\n",n_rx);
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
        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':
377 378
      print_perf=1;
      opp_enabled=1;
379 380 381 382 383 384 385 386 387 388 389
      break;
      
    case 'I':
      run_initial_sync=1;
      target_error_rate=0.1;
      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 414 415 416
    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");
417 418
      //printf("-p Use extended prefix mode\n");
      //printf("-d Use TDD\n");
419 420 421 422 423
      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");
424
      printf("-y Number of TX antennas used in gNB\n");
425
      printf("-z Number of RX antennas used in UE\n");
426 427
      //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");
428 429 430
      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");
431 432
      //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");
433
      printf("-F Input filename (.txt format) for RX conformance testing\n");
434
      printf("-E used CSS scheduler\n");
435
      printf("-o CORESET offset\n");
436 437
      printf("-a Start PRB for PDSCH\n");
      printf("-b Number of PRB for PDSCH\n");
438 439
      printf("-c Start symbol for PDSCH (fixed for now)\n");
      printf("-j Number of symbols for PDSCH (fixed for now)\n");
440
      printf("-e MSC index\n");
441 442 443 444
      exit (-1);
      break;
    }
  }
Raymond Knopp's avatar
Raymond Knopp committed
445
  
446 447 448 449 450 451 452 453
  logInit();
  set_glog(loglvl);
  T_stdout = 1;

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


454 455 456
  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
457

458
  gNB = RC.gNB[0];
459 460 461 462 463 464
  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
465 466 467 468
  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
469
  memset((void*)&rrc,0,sizeof(rrc));
Raymond Knopp's avatar
Raymond Knopp committed
470
  // read in SCGroupConfig
Raymond Knopp's avatar
Raymond Knopp committed
471 472
  FILE *scg_fd = fopen("reconfig.raw","r");
  AssertFatal(scg_fd != NULL,"no reconfig.raw file\n");
Raymond Knopp's avatar
Raymond Knopp committed
473 474 475 476
  char buffer[1024];
  int msg_len=fread(buffer,1,1024,scg_fd);
  NR_RRCReconfiguration_t *NR_RRCReconfiguration;

Raymond Knopp's avatar
Raymond Knopp committed
477
  printf("Decoding NR_RRCReconfiguration (%d bytes)\n",msg_len);
Raymond Knopp's avatar
Raymond Knopp committed
478 479 480 481 482 483 484 485 486 487 488 489 490 491
  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
492 493
  AssertFatal(NR_RRCReconfiguration->criticalExtensions.present == NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration,"wrong NR_RRCReconfiguration->criticalExstions.present type\n");

Raymond Knopp's avatar
Raymond Knopp committed
494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510
  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
511
  xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup);
Raymond Knopp's avatar
Raymond Knopp committed
512

Raymond Knopp's avatar
Raymond Knopp committed
513 514 515 516
  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
517

Raymond Knopp's avatar
Raymond Knopp committed
518 519
  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
520
  // common configuration
521
  rrc_mac_config_req_gNB(0,0,1,scc,0,0,NULL);
Raymond Knopp's avatar
Raymond Knopp committed
522
  // UE dedicated configuration
523
  rrc_mac_config_req_gNB(0,0,1,NULL,1,secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity,secondaryCellGroup);
Raymond Knopp's avatar
Raymond Knopp committed
524
  phy_init_nr_gNB(gNB,0,0);
525
  N_RB_DL = gNB->frame_parms.N_RB_DL;
Raymond Knopp's avatar
Raymond Knopp committed
526
  // stub to configure frame_parms
Raymond Knopp's avatar
Raymond Knopp committed
527
  //  nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions);
Raymond Knopp's avatar
Raymond Knopp committed
528 529 530
  // call MAC to configure common parameters


531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553
  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;
  }
  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,
554 555
 				fs,
				bw,
556 557 558 559 560
                                0,
                                0,
                                0);

  if (gNB2UE==NULL) {
561
    printf("Problem generating channel model. Exiting.\n");
562 563 564 565
    exit(-1);
  }

  frame_length_complex_samples = frame_parms->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
566
  frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587

  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));
588
    bzero(txdata[i],frame_length_complex_samples*sizeof(int));
589 590 591 592 593 594 595 596 597 598
  
  }

  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
599
  memset((void*)UE,0,sizeof(PHY_VARS_NR_UE));
600 601 602 603
  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
604

605
  if (run_initial_sync==1)  UE->is_synchronized = 0;
606
  else                      {UE->is_synchronized = 1; UE->UE_mode[0]=PUSCH;}
607 608
                      
  UE->perfect_ce = 0;
609
  for (i=0;i<10;i++) UE->current_thread_id[i] = 0;
610 611 612 613 614 615 616

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

617 618
  init_nr_ue_transport(UE,0);

619
  nr_gold_pbch(UE);
620
  nr_gold_pdcch(UE,0,2);
621 622


623
   
624
  nr_l2_init_ue(NULL);
625
  UE_mac = get_mac_inst(0);
Guy De Souza's avatar
Guy De Souza committed
626
  
627 628 629
  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;
630
  UE->if_inst->dl_indication = nr_ue_dl_indication;
631 632 633
  UE->if_inst->ul_indication = dummy_nr_ue_ul_indication;
  

634
  UE_mac->if_module = nr_ue_if_module_init(0);
Ahmed Hussein's avatar
Ahmed Hussein committed
635
  
636
  unsigned int available_bits=0;
Ahmed Hussein's avatar
Ahmed Hussein committed
637 638 639 640 641
  unsigned char *estimated_output_bit;
  unsigned char *test_input_bit;
  unsigned int errors_bit    = 0;
  uint32_t errors_scrambling = 0;

642

Ahmed Hussein's avatar
Ahmed Hussein committed
643 644
  test_input_bit       = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384);
  estimated_output_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384);
645 646
  
  // generate signal
647 648 649 650 651 652 653 654
  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;
  
655

Raymond Knopp's avatar
Raymond Knopp committed
656

657
  //Configure UE
658 659
  rrc.carrier.MIB = (uint8_t*) malloc(4);
  rrc.carrier.sizeof_MIB = do_MIB_NR(&rrc,0);
660

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

663 664 665 666 667 668 669 670

  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;
671
  
672 673 674 675 676 677 678
  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;
679
  
Francesco Mani's avatar
Francesco Mani committed
680

681 682
  nr_ue_phy_config_request(&UE_mac->phy_config);

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

685 686 687 688 689 690 691 692 693 694 695 696 697
    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);  

698
    n_errors = 0;
699 700
    //n_errors2 = 0;
    //n_alamouti = 0;
701
    errors_scrambling=0;
702
    n_false_positive = 0;
Ahmed Hussein's avatar
Ahmed Hussein committed
703
    for (trial = 0; trial < n_trials; trial++) {
704

705
      errors_bit = 0;
Ahmed Hussein's avatar
Ahmed Hussein committed
706
      //multipath channel
707
      //multipath_channel(gNB2UE,s_re,s_im,r_re,r_im,frame_length_complex_samples,0);
708 709 710 711 712 713 714 715 716 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

      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));
      
769 770 771
      for (i=(slot * frame_parms->samples_per_slot); 
	   i<((slot+1) * frame_parms->samples_per_slot); 
	   i++) {
772 773 774 775 776 777 778 779
	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;
780 781
      
      //AWGN
782
      sigma2_dB = 10 * log10((double)txlev * ((double)UE->frame_parms.ofdm_symbol_size/(12*rel15.rbSize))) - SNR;
Ahmed Hussein's avatar
Ahmed Hussein committed
783
      sigma2    = pow(10, sigma2_dB/10);
784
      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));
785
      
786 787 788
      for (i=(slot * frame_parms->samples_per_slot); 
	   i<((slot+1) * frame_parms->samples_per_slot); 
	   i++) {
789 790 791 792 793
	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)));
	}
      }
794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840
      
      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
841
	
842 843 844 845 846 847
	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
848
	    }
849
	    errors_scrambling++;
Raymond Knopp's avatar
Raymond Knopp committed
850 851
	  }
	
852 853
      }
      for (i = 0; i < TBS; i++) {
Raymond Knopp's avatar
Raymond Knopp committed
854
	
855 856
	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
857
	
858 859 860 861
	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
862 863
	}
	
864 865 866 867 868 869
      }
      
      ////////////////////////////////////////////////////////////
      
      if (errors_scrambling > 0) {
	if (n_trials == 1)
870
	  printf("errors_scrambling = %d/%d (trial %d)\n", errors_scrambling, available_bits,trial);
871 872 873 874 875 876 877
      }
      
      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
878
      
Ahmed Hussein's avatar
Ahmed Hussein committed
879
    } // noise trials
880

Ahmed Hussein's avatar
Ahmed Hussein committed
881 882
    printf("*****************************************\n");
    printf("SNR %f, (false positive %f)\n", SNR,
Sakthivel Velumani's avatar
Sakthivel Velumani committed
883
           (float) n_errors / (float) n_trials);
Ahmed Hussein's avatar
Ahmed Hussein committed
884 885
    printf("*****************************************\n");
    printf("\n");
886
    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
887
    printf("\n");
888

889 890 891 892 893 894 895 896 897 898
    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;
    }

899
    if ((float)n_errors/(float)n_trials <= target_error_rate) {
Sakthivel Velumani's avatar
Sakthivel Velumani committed
900
      printf("PDSCH test OK\n");
901 902 903
      break;
    }

904 905

    if (print_perf==1) {
906 907 908 909 910
      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));
911 912 913 914 915 916 917 918 919 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
      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");
      */
    }
955 956
  } // NSR

Ahmed Hussein's avatar
Ahmed Hussein committed
957
  for (i = 0; i < 2; i++) {
958 959 960 961 962 963 964 965 966 967 968 969
    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
970 971 972
  free(test_input_bit);
  free(estimated_output_bit);
  
973 974 975 976 977 978 979
  if (output_fd)
    fclose(output_fd);

  if (input_fd)
    fclose(input_fd);

  return(n_errors);
Raymond Knopp's avatar
Raymond Knopp committed
980
  
981
}