mbmssim.c 16.8 KB
Newer Older
1 2 3 4 5
/*
 * 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
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7 8 9 10 11 12 13 14 15 16 17 18 19 20
 * 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
 */
ghaddab's avatar
ghaddab committed
21

22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
#include <string.h>
#include <math.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>

#include "SIMULATION/TOOLS/defs.h"
#include "SIMULATION/RF/defs.h"
#include "PHY/types.h"
#include "PHY/defs.h"
#include "PHY/vars.h"
#include "SCHED/defs.h"
#include "SCHED/vars.h"
#include "LAYER2/MAC/vars.h"

#ifdef XFORMS
39
#include "PHY/TOOLS/lte_phy_scope.h"
40 41 42 43
#endif //XFORMS


#include "OCG_vars.h"
44
#include "unitary_defs.h"
45 46


47 48
PHY_VARS_eNB *eNB;
PHY_VARS_UE *UE;
49

50
double cpuf;
51 52 53

DCI1E_5MHz_2A_M10PRB_TDD_t  DLSCH_alloc_pdu2_1E[2];
#define UL_RB_ALLOC 0x1ff;
54
#define CCCH_RB_ALLOC computeRIV(eNB->frame_parms.N_RB_UL,0,2)
55 56
int main(int argc, char **argv)
{
57 58 59

  char c;

60
  int i,l,l2,aa,aarx,k;
61
  double sigma2, sigma2_dB=0,SNR,snr0=-2.0,snr1=0.0;
62
  uint8_t snr1set=0;
63 64
  double snr_step=1,input_snr_step=1;
  int **txdata;
65 66 67
  double s_re0[2*30720],s_im0[2*30720],s_re1[2*30720],s_im1[2*30720];
  double r_re0[2*30720],r_im0[2*30720],r_re1[2*30720],r_im1[2*30720];
  double *s_re[2]={s_re0,s_re1},*s_im[2]={s_im0,s_im1},*r_re[2]={r_re0,r_re1},*r_im[2]={r_im0,r_im1};
68 69 70
  double iqim = 0.0;
  int subframe=1;
  char fname[40];//, vname[40];
71 72
  uint8_t transmission_mode = 1,n_tx=1,n_rx=2;
  uint16_t Nid_cell=0;
73 74 75 76 77 78 79 80

  FILE *fd;

  int eNB_id = 0;
  unsigned char mcs=0,awgn_flag=0,round;

  int n_frames=1;
  channel_desc_t *eNB2UE;
81 82
  uint32_t nsymb,tx_lev,tx_lev_dB;
  uint8_t extended_prefix_flag=1;
83 84 85
  LTE_DL_FRAME_PARMS *frame_parms;
  int hold_channel=0;

86

87
  uint16_t NB_RB=25;
88 89

  int tdd_config=3;
90

91 92 93 94 95 96
  SCM_t channel_model=MBSFN;


  unsigned char *input_buffer;
  unsigned short input_buffer_length;
  unsigned int ret;
97 98 99

  unsigned int trials,errs[4]= {0,0,0,0}; //,round_trials[4]={0,0,0,0};

100
  uint8_t N_RB_DL=25,osf=1;
Raymond Knopp's avatar
 
Raymond Knopp committed
101
  uint32_t perfect_ce = 0;
102

103
  lte_frame_type_t frame_type = FDD;
104

105
  uint32_t Nsoft = 1827072;
106

107
  /*
108
#ifdef XFORMS
109
  FD_lte_phy_scope_ue *form_ue;
110 111 112
  char title[255];

  fl_initialize (&argc, argv, NULL, 0, 0);
113
  form_ue = create_lte_phy_scope_ue();
114
  sprintf (title, "LTE DL SCOPE UE");
115
  fl_show_form (form_ue->lte_phy_scope_ue, FL_PLACE_HOTSPOT, FL_FULLBORDER, title);
116
#endif
117
  */
118

119 120
  cpuf = get_cpu_freq_GHz();

121 122
  logInit();
  number_of_cards = 1;
123 124 125 126 127 128 129 130 131 132 133 134 135 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 167 168 169 170 171 172 173 174 175 176 177

  while ((c = getopt (argc, argv, "ahA:Cp:n:s:S:t:x:y:z:N:F:R:O:dm:i:Y")) != -1) {
    switch (c) {
    case 'a':
      awgn_flag=1;
      break;

    case 'd':
      frame_type = 0;
      break;

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

    case 'm':
      mcs=atoi(optarg);
      break;

    case 's':
      snr0 = atof(optarg);
      msg("Setting SNR0 to %f\n",snr0);
      break;

    case 'i':
      input_snr_step = atof(optarg);
      break;

    case 'S':
      snr1 = atof(optarg);
      snr1set=1;
      msg("Setting SNR1 to %f\n",snr1);
      break;

    case 'p': // subframe no;
      subframe=atoi(optarg);
      break;

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

      if ((n_rx==0) || (n_rx>2)) {
        msg("Unsupported number of rx antennas %d\n",n_rx);
        exit(-1);
      }

      break;

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

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

Florian Kaltenberger's avatar
Florian Kaltenberger committed
178
      if ((N_RB_DL!=6) && (N_RB_DL!=25) && (N_RB_DL!=50) && (N_RB_DL!=100))  {
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
        printf("Unsupported Bandwidth %d\n",N_RB_DL);
        exit(-1);
      }

      break;

    case 'O':
      osf = atoi(optarg);
      break;

    case 'Y':
      perfect_ce = 1;
      break;

    default:
    case 'h':
      printf("%s -h(elp) -p(subframe) -N cell_id -g channel_model -n n_frames -t Delayspread -s snr0 -S snr1 -i snr increment -z RXant \n",argv[0]);
      printf("-h This message\n");
      printf("-a Use AWGN Channel\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("-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");
      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");
      printf("-F Input filename (.txt format) for RX conformance testing\n");
      exit (-1);
      break;
219
    }
220 221
  }

222 223


224 225 226 227 228 229 230
  if (awgn_flag == 1)
    channel_model = AWGN;

  // check that subframe is legal for eMBMS

  if ((subframe == 0) || (subframe == 5) ||    // TDD and FDD SFn 0,5;
      ((frame_type == FDD) && ((subframe == 4) || (subframe == 9))) || // FDD SFn 4,9;
231 232
      ((frame_type == TDD ) && ((subframe<3) || (subframe==6))))    {  // TDD SFn 1,2,6;

233 234
    printf("Illegal subframe %d for eMBMS transmission (frame_type %d)\n",subframe,frame_type);
    exit(-1);
235 236
  }

237 238 239
  if (transmission_mode==2)
    n_tx=2;

240
  lte_param_init(n_tx,
241
                 n_tx,
242 243 244 245 246 247 248 249 250 251
		 n_rx,
		 transmission_mode,
		 extended_prefix_flag,
		 frame_type,
		 Nid_cell,
		 tdd_config,
		 N_RB_DL,
		 0,
		 osf,
		 perfect_ce);
252 253 254 255 256 257 258 259 260 261

  if (snr1set==0) {
    if (n_frames==1)
      snr1 = snr0+.1;
    else
      snr1 = snr0+5.0;
  }

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

262
  frame_parms = &eNB->frame_parms;
263 264

  if (awgn_flag == 0)
265
    sprintf(fname,"embms_%d_%d.m",mcs,N_RB_DL);
266 267
  else
    sprintf(fname,"embms_awgn_%d_%d.m",mcs,N_RB_DL);
268

269 270 271 272 273
  if (!(fd = fopen(fname,"w"))) {
    printf("Cannot open %s, check permissions\n",fname);
    exit(-1);
  }
	
274 275

  if (awgn_flag==0)
276
    fprintf(fd,"SNR_%d_%d=[];errs_mch_%d_%d=[];mch_trials_%d_%d=[];\n",
277 278 279
            mcs,N_RB_DL,
            mcs,N_RB_DL,
            mcs,N_RB_DL);
280 281
  else
    fprintf(fd,"SNR_awgn_%d_%d=[];errs_mch_awgn_%d_%d=[];mch_trials_awgn_%d_%d=[];\n",
282 283 284 285
            mcs,N_RB_DL,
            mcs,N_RB_DL,
            mcs,N_RB_DL);

286 287
  fflush(fd);

288
  txdata = eNB->common_vars.txdata[0];
289 290 291 292

  nsymb = 12;

  printf("FFT Size %d, Extended Prefix %d, Samples per subframe %d, Symbols per subframe %d, AWGN %d\n",NUMBER_OF_OFDM_CARRIERS,
293
         frame_parms->Ncp,frame_parms->samples_per_tti,nsymb,awgn_flag);
294

295 296
  eNB2UE = new_channel_desc_scm(eNB->frame_parms.nb_antennas_tx,
                                UE->frame_parms.nb_antennas_rx,
297
                                channel_model,
298 299
				N_RB2sampling_rate(eNB->frame_parms.N_RB_DL),
				N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL),
300 301 302 303 304
                                0,
                                0,
                                0);

  // Create transport channel structures for 2 transport blocks (MIMO)
305
  eNB->dlsch_MCH = new_eNB_dlsch(1,8,Nsoft,N_RB_DL,0,&eNB->frame_parms);
306

307
  if (!eNB->dlsch_MCH) {
308 309 310
    printf("Can't get eNB dlsch structures\n");
    exit(-1);
  }
311

312
  UE->dlsch_MCH[0]  = new_ue_dlsch(1,8,Nsoft,MAX_TURBO_ITERATIONS_MBSFN,N_RB_DL,0);
313

314 315 316 317 318 319 320 321 322 323
  eNB->frame_parms.num_MBSFN_config = 1;
  eNB->frame_parms.MBSFN_config[0].radioframeAllocationPeriod = 0;
  eNB->frame_parms.MBSFN_config[0].radioframeAllocationOffset = 0;
  eNB->frame_parms.MBSFN_config[0].fourFrames_flag = 0;
  eNB->frame_parms.MBSFN_config[0].mbsfn_SubframeConfig=0xff; // activate all possible subframes
  UE->frame_parms.num_MBSFN_config = 1;
  UE->frame_parms.MBSFN_config[0].radioframeAllocationPeriod = 0;
  UE->frame_parms.MBSFN_config[0].radioframeAllocationOffset = 0;
  UE->frame_parms.MBSFN_config[0].fourFrames_flag = 0;
  UE->frame_parms.MBSFN_config[0].mbsfn_SubframeConfig=0xff; // activate all possible subframes
324

325 326
  fill_eNB_dlsch_MCH(eNB,mcs,1,0);
  fill_UE_dlsch_MCH(UE,mcs,1,0,0);
327

328
  if (is_pmch_subframe(0,subframe,&eNB->frame_parms)==0) {
329 330
    printf("eNB is not configured for MBSFN in subframe %d\n",subframe);
    exit(-1);
331
  } else if (is_pmch_subframe(0,subframe,&UE->frame_parms)==0) {
332
    printf("UE is not configured for MBSFN in subframe %d\n",subframe);
333
    exit(-1);
334 335 336
  }


337
  input_buffer_length = eNB->dlsch_MCH->harq_processes[0]->TBS/8;
338 339
  input_buffer = (unsigned char *)malloc(input_buffer_length+4);
  memset(input_buffer,0,input_buffer_length+4);
340 341

  for (i=0; i<input_buffer_length+4; i++) {
342 343 344 345 346
    input_buffer[i]= (unsigned char)(taus()&0xff);
  }


  snr_step = input_snr_step;
347 348

  for (SNR=snr0; SNR<snr1; SNR+=snr_step) {
349 350 351
    UE->proc.proc_rxtx[0].frame_tx=0;
    eNB->proc.proc_rxtx[0].frame_tx=0;
    eNB->proc.proc_rxtx[0].subframe_tx=subframe;
352

353 354 355 356 357 358 359 360 361 362 363
    errs[0]=0;
    errs[1]=0;
    errs[2]=0;
    errs[3]=0;
    /*
    round_trials[0] = 0;
    round_trials[1] = 0;
    round_trials[2] = 0;
    round_trials[3] = 0;*/
    printf("********************** SNR %f (step %f)\n",SNR,snr_step);

364
    for (trials = 0; trials<n_frames; trials++) {
365 366 367
      //        printf("Trial %d\n",trials);
      fflush(stdout);
      round=0;
368

369 370 371
      //if (trials%100==0)
      //eNB2UE[0]->first_run = 1;
      eNB2UE->first_run = 1;
372 373
      memset(&eNB->common_vars.txdataF[0][0][0],0,FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX*sizeof(int32_t));
      generate_mch(eNB,&eNB->proc.proc_rxtx[0],input_buffer);
374

375

376
      PHY_ofdm_mod(eNB->common_vars.txdataF[0][0],        // input,
377
                   txdata[0],         // output
378
                   frame_parms->ofdm_symbol_size,
379 380 381
                   LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*nsymb,                 // number of symbols
                   frame_parms->nb_prefix_samples,               // number of prefix samples
                   CYCLIC_PREFIX);
382 383

      if (n_frames==1) {
384 385 386 387
        write_output("txsigF0.m","txsF0", &eNB->common_vars.txdataF[0][0][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size],
                     nsymb*eNB->frame_parms.ofdm_symbol_size,1,1);
        //if (eNB->frame_parms.nb_antennas_tx>1)
        //write_output("txsigF1.m","txsF1", &eNB->lte_eNB_common_vars.txdataF[eNB_id][1][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size],nsymb*eNB->frame_parms.ofdm_symbol_size,1,1);
388 389 390
      }

      tx_lev = 0;
391

392 393 394 395
      for (aa=0; aa<eNB->frame_parms.nb_antennas_tx; aa++) {
        tx_lev += signal_energy(&eNB->common_vars.txdata[eNB_id][aa]
                                [subframe*eNB->frame_parms.samples_per_tti],
                                eNB->frame_parms.samples_per_tti);
396
      }
397

398
      tx_lev_dB = (unsigned int) dB_fixed(tx_lev);
399

400
      if (n_frames==1) {
401
        printf("tx_lev = %d (%d dB)\n",tx_lev,tx_lev_dB);
402
        //    write_output("txsig0.m","txs0", &eNB->common_vars.txdata[0][0][subframe* eNB->frame_parms.samples_per_tti],
403

404
        //     eNB->frame_parms.samples_per_tti,1,1);
405
      }
406

407

408
      for (i=0; i<2*frame_parms->samples_per_tti; i++) {
409 410 411
        for (aa=0; aa<eNB->frame_parms.nb_antennas_tx; aa++) {
          s_re[aa][i] = ((double)(((short *)eNB->common_vars.txdata[0][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) + (i<<1)]);
          s_im[aa][i] = ((double)(((short *)eNB->common_vars.txdata[0][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)+1]);
412
        }
413
      }
414

415 416
      //Multipath channel
      multipath_channel(eNB2UE,s_re,s_im,r_re,r_im,
417 418
                        2*frame_parms->samples_per_tti,hold_channel);

419
      //AWGN
420
      sigma2_dB = 10*log10((double)tx_lev) +10*log10((double)eNB->frame_parms.ofdm_symbol_size/(NB_RB*12)) - SNR;
421
      sigma2 = pow(10,sigma2_dB/10);
422

423
      if (n_frames==1)
424 425
        printf("Sigma2 %f (sigma2_dB %f)\n",sigma2,sigma2_dB);

426
      for (i=0; i<2*frame_parms->samples_per_tti; i++) {
427
        for (aa=0; aa<eNB->frame_parms.nb_antennas_rx; aa++) {
428
          //printf("s_re[0][%d]=> %f , r_re[0][%d]=> %f\n",i,s_re[aa][i],i,r_re[aa][i]);
429
          ((short*) UE->common_vars.rxdata[aa])[(2*subframe*UE->frame_parms.samples_per_tti)+2*i] =
430
            (short) (r_re[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0));
431
          ((short*) UE->common_vars.rxdata[aa])[(2*subframe*UE->frame_parms.samples_per_tti)+2*i+1] =
432 433
            (short) (r_im[aa][i] + (iqim*r_re[aa][i]) + sqrt(sigma2/2)*gaussdouble(0.0,1.0));
        }
434 435
      }

436 437
      for (l=2; l<12; l++) {

438
        slot_fep_mbsfn(UE,
439 440 441 442
                       l,
                       subframe%10,
                       0,
                       0);
443
	if (UE->perfect_ce==1) {
444
	  // fill in perfect channel estimates
445
	  freq_channel(eNB2UE,UE->frame_parms.N_RB_DL,12*UE->frame_parms.N_RB_DL + 1);
446 447 448 449
	  for(k=0; k<NUMBER_OF_eNB_MAX; k++) {
	    for(aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
	      for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
		for (i=0; i<frame_parms->N_RB_DL*12; i++) {
450 451
		  ((int16_t *) UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[k][(aa<<1)+aarx])[2*i+(l*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(int16_t)(eNB2UE->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].x*AMP);
		  ((int16_t *) UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[k][(aa<<1)+aarx])[2*i+1+(l*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(int16_t)(eNB2UE->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].y*AMP);
452 453 454 455 456
		}
	      }
	    }
	  }
	}
457 458 459

	if (l==6)
          for (l2=2;l2<7;l2++)
460
	    rx_pmch(UE,
461 462 463 464 465
		    0,
		    subframe%10,
		    l2);
	if (l==6)
          for (l2=2;l2<7;l2++)
466
	    rx_pmch(UE,
467 468 469 470 471
		    0,
		    subframe%10,
		    l2);
	if (l==11)
          for (l2=7;l2<12;l2++)
472
	    rx_pmch(UE,
473 474 475
		    0,
		    subframe%10,
		    l2);
476 477
      }

478
      UE->dlsch_MCH[0]->harq_processes[0]->G = get_G(&UE->frame_parms,
479 480 481 482 483
						     UE->dlsch_MCH[0]->harq_processes[0]->nb_rb,
						     UE->dlsch_MCH[0]->harq_processes[0]->rb_alloc_even,
						     get_Qm(UE->dlsch_MCH[0]->harq_processes[0]->mcs),
						     1,2,
						     UE->proc.proc_rxtx[0].frame_tx,subframe,0);
484 485 486 487 488 489 490 491 492 493 494
      UE->dlsch_MCH[0]->harq_processes[0]->Qm = get_Qm(UE->dlsch_MCH[0]->harq_processes[0]->mcs);

      dlsch_unscrambling(&UE->frame_parms,1,UE->dlsch_MCH[0],
                         UE->dlsch_MCH[0]->harq_processes[0]->G,
                         UE->pdsch_vars_MCH[0]->llr[0],0,subframe<<1);

      ret = dlsch_decoding(UE,
                           UE->pdsch_vars_MCH[0]->llr[0],
                           &UE->frame_parms,
                           UE->dlsch_MCH[0],
                           UE->dlsch_MCH[0]->harq_processes[0],
495
                           trials,
496 497 498
                           subframe,
                           0,0,0);

499
      if (n_frames==1)
500 501
        printf("MCH decoding returns %d\n",ret);

502
      if (ret == (1+UE->dlsch_MCH[0]->max_turbo_iterations))
503 504
        errs[0]++;

505 506
      UE->proc.proc_rxtx[0].frame_tx++;
      eNB->proc.proc_rxtx[0].frame_tx++;
507
    }
508

509 510 511
    printf("errors %d/%d (Pe %e)\n",errs[round],trials,(double)errs[round]/trials);

    if (awgn_flag==0)
Raymond Knopp's avatar
 
Raymond Knopp committed
512
      fprintf(fd,"SNR_%d_%d = [SNR_%d_%d %f]; errs_mch_%d_%d =[errs_mch_%d_%d  %d]; mch_trials_%d_%d =[mch_trials_%d_%d  %d];\n",
513 514 515
              mcs,N_RB_DL,mcs,N_RB_DL,SNR,
              mcs,N_RB_DL,mcs,N_RB_DL,errs[0],
              mcs,N_RB_DL,mcs,N_RB_DL,trials);
516
    else
Cedric Roux's avatar
Cedric Roux committed
517 518 519 520
      fprintf(fd,"SNR_awgn_%d = [SNR_awgn_%d %f]; errs_mch_awgn_%d =[errs_mch_awgn_%d  %d]; mch_trials_awgn_%d =[mch_trials_awgn_%d %d];\n",
              N_RB_DL,N_RB_DL,SNR,
              N_RB_DL,N_RB_DL,errs[0],
              N_RB_DL,N_RB_DL,trials);
521

522
    fflush(fd);
523

524 525
    if (errs[0] == 0)
      break;
526
  }
527 528 529


  if (n_frames==1) {
530 531 532
    printf("Dumping PMCH files ( G %d)\n",UE->dlsch_MCH[0]->harq_processes[0]->G);
    dump_mch(UE,0,
             UE->dlsch_MCH[0]->harq_processes[0]->G,
533
             subframe);
534
  }
535

536
  printf("Freeing dlsch structures\n");
537 538
  free_eNB_dlsch(eNB->dlsch_MCH);
  free_ue_dlsch(UE->dlsch_MCH[0]);
539 540

  fclose(fd);
541

542
  return(0);
543 544
}