void multipath_channel(channel_desc_t *desc,
                       double **tx_sig_re,
                       double **tx_sig_im,
                       double **rx_sig_re,
                       double **rx_sig_im,
                       uint32_t length,
                       uint8_t keep_channel)
{

  int i,ii,j,l;
  int length1, length2, tail;
  __m128d rx_tmp128_re_f,rx_tmp128_im_f,rx_tmp128_re,rx_tmp128_im, rx_tmp128_1,rx_tmp128_2,rx_tmp128_3,rx_tmp128_4,tx128_re,tx128_im,ch128_x,ch128_y,pathloss128;

  double path_loss = pow(10,desc->path_loss_dB/20);
  int dd = abs(desc->channel_offset);

  pathloss128 = _mm_set1_pd(path_loss);

#ifdef DEBUG_CH
  printf("[CHANNEL] keep = %d : path_loss = %g (%f), nb_rx %d, nb_tx %d, dd %d, len %d \n",keep_channel,path_loss,desc->path_loss_dB,desc->nb_rx,desc->nb_tx,dd,desc->channel_length);
#endif

  if (keep_channel) {
    // do nothing - keep channel
  } else {
    random_channel(desc,0);
  }

  start_meas(&desc->convolution);

#ifdef DEBUG_CH

  for (l = 0; l<(int)desc->channel_length; l++) {
    printf("%p (%f,%f) ",desc->ch[0],desc->ch[0][l].x,desc->ch[0][l].y);
  }

  printf("\n");
#endif

  tail = ((int)length-dd)%2;

  if(tail)
    length1 = ((int)length-dd)-1;
  else
    length1 = ((int)length-dd);

  length2 = length1/2;

  for (i=0; i<length2; i++) { //
    for (ii=0; ii<desc->nb_rx; ii++) {
      // rx_tmp.x = 0;
      // rx_tmp.y = 0;
      rx_tmp128_re_f = _mm_setzero_pd();
      rx_tmp128_im_f = _mm_setzero_pd();

      for (j=0; j<desc->nb_tx; j++) {
        for (l = 0; l<(int)desc->channel_length; l++) {
          if ((i>=0) && (i-l)>=0) { //SIMD correct only if length1 > 2*channel_length...which is almost always satisfied
            // tx.x = tx_sig_re[j][i-l];
            // tx.y = tx_sig_im[j][i-l];
            tx128_re = _mm_loadu_pd(&tx_sig_re[j][2*i-l]); // tx_sig_re[j][i-l+1], tx_sig_re[j][i-l]
            tx128_im = _mm_loadu_pd(&tx_sig_im[j][2*i-l]);
          } else {
            //tx.x =0;
            //tx.y =0;
            tx128_re = _mm_setzero_pd();
            tx128_im = _mm_setzero_pd();
          }

          ch128_x = _mm_set1_pd(desc->ch[ii+(j*desc->nb_rx)][l].x);
          ch128_y = _mm_set1_pd(desc->ch[ii+(j*desc->nb_rx)][l].y);
          //  rx_tmp.x += (tx.x * desc->ch[ii+(j*desc->nb_rx)][l].x) - (tx.y * desc->ch[ii+(j*desc->nb_rx)][l].y);
          //  rx_tmp.y += (tx.y * desc->ch[ii+(j*desc->nb_rx)][l].x) + (tx.x * desc->ch[ii+(j*desc->nb_rx)][l].y);
          rx_tmp128_1 = _mm_mul_pd(tx128_re,ch128_x);
          rx_tmp128_2 = _mm_mul_pd(tx128_re,ch128_y);
          rx_tmp128_3 = _mm_mul_pd(tx128_im,ch128_x);
          rx_tmp128_4 = _mm_mul_pd(tx128_im,ch128_y);
          rx_tmp128_re = _mm_sub_pd(rx_tmp128_1,rx_tmp128_4);
          rx_tmp128_im = _mm_add_pd(rx_tmp128_2,rx_tmp128_3);
          rx_tmp128_re_f = _mm_add_pd(rx_tmp128_re_f,rx_tmp128_re);
          rx_tmp128_im_f = _mm_add_pd(rx_tmp128_im_f,rx_tmp128_im);
        } //l
      }  // j

      //rx_sig_re[ii][i+dd] = rx_tmp.x*path_loss;
      //rx_sig_im[ii][i+dd] = rx_tmp.y*path_loss;
      rx_tmp128_re_f = _mm_mul_pd(rx_tmp128_re_f,pathloss128);
      rx_tmp128_im_f = _mm_mul_pd(rx_tmp128_im_f,pathloss128);
      _mm_storeu_pd(&rx_sig_re[ii][2*i+dd],rx_tmp128_re_f); // max index: length-dd -1 + dd = length -1
      _mm_storeu_pd(&rx_sig_im[ii][2*i+dd],rx_tmp128_im_f);
      /*
      if ((ii==0)&&((i%32)==0)) {
      printf("%p %p %f,%f => %e,%e\n",rx_sig_re[ii],rx_sig_im[ii],rx_tmp.x,rx_tmp.y,rx_sig_re[ii][i-dd],rx_sig_im[ii][i-dd]);
      }
      */
      //rx_sig_re[ii][i] = sqrt(.5)*(tx_sig_re[0][i] + tx_sig_re[1][i]);
      //rx_sig_im[ii][i] = sqrt(.5)*(tx_sig_im[0][i] + tx_sig_im[1][i]);

    } // ii
  } // i

  stop_meas(&desc->convolution);

}
//#define DEBUG_CH
uint8_t multipath_channel_nosigconv(channel_desc_t *desc)
{

  random_channel(desc,0);
  return(1);
}
예제 #3
0
// Leosam 08/08: What are the arguments?
int
main (int argc, char **argv)
{

	// Command line parsing
	int input_val = 1000;	// Value serving as an input relatad to the SNR
	int max_num_ofdm_sym = 64;	// Index of the last frame for the channel estimation
	int be_verbose = 0;	// Operate in verbose mode
	int index;
	int c;
	unsigned int rx_energy[NB_ANTENNAS], n0_energy[NB_ANTENNAS];

	if (argc == 1)
	{
		error ();
		exit (-1);
	}

	while ((c = getopt (argc, argv, "hVv:n:")) != -1)
	{
		switch (c)
		{
		case 'h':
			help ();
			exit (1);
		case 'V':
			be_verbose = 1;
			break;
		case 'v':
			input_val = atoi (optarg);
			break;
			return 1;
		case 'n':
			max_num_ofdm_sym = atoi (optarg);
			break;
			return 1;
		default:
			error ();
			exit (-1);
		}
	}

	//
	// Initialization stuff
	//

	int i, ii, j, ret, delay, l;
	short seed[3];

	// Leosam 08/08: What is this amps?
	double amps[8] = { 1.0, .8, .4, .2, .1, .05, .025, .01 };
	struct complex ch[NB_ANTENNAS * NB_ANTENNAS][10 + (int) (1 + 2 * BW * Td)];
	struct complex rx_tmp, tx, n, phase;

	char *chbch_pdu;
	int chbch_size;
	int extension;
	unsigned char dummy_mac_pdu[120];

#ifdef USER_MODE
  char fname[40], vname[40];
#endif // USER_MODE

	if (be_verbose)
		printf ("Allocating memory for PHY_VARS\n");

	// Memory allocation for PHY and MAC structures
	PHY_vars = malloc (sizeof (PHY_VARS));
	PHY_config = malloc (sizeof (PHY_CONFIG));
	mac_xface = malloc (sizeof (MAC_xface));

	// Loading of the configuration data
	if ((config = fopen ("config.cfg", "r")) == NULL)	// this can be configured
	{
		if (be_verbose)
			printf ("[Main USER] The openair configuration file <config.cfg> could not be found!\n");
		exit (0);
	}

	if ((scenario = fopen ("scenario.scn", "r")) == NULL)
	{
		if (be_verbose)
			printf ("[Main USER] The openair scenario file <scenario.scn> could not be found!\n");
		exit (0);
	}

	if (be_verbose)
		printf ("Opened configuration files\n");

	reconfigure_MACPHY (scenario);

	if (be_verbose)
		dump_config ();

	//  Leosam 08/08: This is repeated bellow. Is it necessary?
	mac_xface->is_cluster_head = 0;

	// Initialize the PHY and MAC variables
	phy_init (NB_ANTENNAS_TX);
	if (be_verbose)
		printf ("Initialized PHY variables\n");


	// Fill MAC PDU buffer for CHBCH
	seed[0] = (short) time (NULL);
	seed[1] = (short) time (NULL);
	seed[2] = (short) time (NULL);
	seed48 (&seed[0]);

	randominit ();

	/*
	 * for (i=0;i<mac_xface->mac_tch->bch_tx[0].size-4;i++) {
	 * mac_xface->mac_tch->bch_tx[0].data[i] = i;//(u8)lrand48();
	 * }
	 * 
	 * 
	 * printf("Filled CHBCH PDU with random data\n");
	 * 
	 * // Generate one CHBCH
	 * phy_generate_chbch(0);
	 * 
	 */

	//
	//  Preparation for the TX procedure
	// 

	// Creation of the CHBCH
	chbch_size = (NUMBER_OF_CARRIERS_PER_GROUP * (NUMBER_OF_CHBCH_SYMBOLS) * 16) >> 3;
	if (be_verbose)
		printf ("chbch_size = %d\n", chbch_size);
	chbch_pdu = malloc (chbch_size);

	for (i = 0; i < chbch_size - 4; i++)
	{
		chbch_pdu[i] = i;
	}

	if (be_verbose)
		printf ("Filled CHBCH PDU (%d bytes) with data\n", chbch_size);

	// Leosam 08/08: O.o
	delay = 1032;
	//	delay = 0;

	// Generation of the CHBCH
	phy_generate_chbch (0, 1, NB_ANTENNAS_TX, chbch_pdu);

	// Generation of the pilot symbols
	for (i = 16; i < max_num_ofdm_sym; i++)
	{
		phy_generate_sch (0, i, 0xFFFF, 1, NB_ANTENNAS_TX);
	}
	
	mac_xface->is_cluster_head = 0;
	
	if (be_verbose)
	{
		for (ii=0; ii<NB_ANTENNAS; ii++)
		{
			sprintf (fname, "txsig%d.m", ii);
			sprintf (vname, "txs%d", ii);

			write_output (fname, vname,
										(s16 *) PHY_vars->tx_vars[ii].TX_DMA_BUFFER,
										NUMBER_OF_SYMBOLS_PER_FRAME * OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES, 1, 1);
		}
	}


	// generate channels
	if (be_verbose)
		printf ("Generating MIMO Channels\n");

	phase.r = 0;
	phase.i = 0;
	
	printf("Phase pointer %0x\n",&phase);

	for (i = 0; i < NB_ANTENNAS; i++)
	{
		for (j = 0; j < NB_ANTENNAS; j++)
		{
			random_channel (amps, Td, 8, BW, ch[j + (i * NB_ANTENNAS)],0.0,&phase);
		}
	}

	if (be_verbose)
		printf ("chbch_pdu %x (%d)\n", PHY_vars->chbch_data[0].demod_pdu, chbch_size);

	if (be_verbose)
	{
		for (l = 0; l < (1 + 2 * BW * Td); l++)
		{
			printf ("(%f,%f)\n", ch[0][l]);
		}
	}

	//
	// TX procedure
	//

	// Transmission 
	//
	//////////////////////////
	
	// Foreach symbol
	for (i = 0; i < (max_num_ofdm_sym) * OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES; i++)
	{
		// Foreach RX antenna
		for (ii = 0; ii < NB_ANTENNAS; ii++)
		{
			rx_tmp.r = 0;
			rx_tmp.i = 0;
			n.r = gaussdouble (0.0, 10.0);
			n.i = gaussdouble (0.0, 10.0);
			
			// Foreach TX antenna
			for (j = 0; j < NB_ANTENNAS; j++)
			{
				
				// Foreach symbol
				for (l = 0; l < (1 + 2 * BW * Td); l++)
				{

					tx.r = (double) (((s16 *) & PHY_vars->tx_vars[j].
							  TX_DMA_BUFFER[0 *
									OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES])
							 [2 * (i - l)]) / sqrt (1.0 * input_val);
					tx.i = (double) (((s16 *) & PHY_vars->tx_vars[j].
							  TX_DMA_BUFFER[0 *
									OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES])
							 [1 +
							  (2 * (i - l))]) / sqrt (1.0 * input_val);

					rx_tmp.r +=
						(tx.r * ch[j + (ii * NB_ANTENNAS)][l].r) -
						(tx.i * ch[j + (ii * NB_ANTENNAS)][l].i);
					rx_tmp.i +=
						(tx.i * ch[j + (ii * NB_ANTENNAS)][l].r) +
						(tx.r * ch[j + (ii * NB_ANTENNAS)][l].i);

				}
			}
 
			((s16 *) & PHY_vars->rx_vars[ii].
			 RX_DMA_BUFFER[delay + (0 * OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES)])[2 * i] =
					(short) (rx_tmp.r + n.r);
			((s16 *) & PHY_vars->rx_vars[ii].
			 RX_DMA_BUFFER[delay + (0 * OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES)])[1 +
											(2 * i)] =
					(short) (rx_tmp.i + n.i);
		}
	}

	if (be_verbose)
	{
		for (ii=0; ii<NB_ANTENNAS; ii++)
		{
			sprintf (fname, "rxsig%d.m", ii);
			sprintf (vname, "rxs%d", ii);

			write_output (fname, vname,
			      (s16 *) PHY_vars->rx_vars[ii].RX_DMA_BUFFER,
						NUMBER_OF_SYMBOLS_PER_FRAME * OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES, 1, 1);
		}
	}

	//
	// RX procedure
	//  

	if (be_verbose)
		printf ("Starting RX\n");

	// Sync
	phy_synch_time (PHY_vars->rx_vars[0].RX_DMA_BUFFER,
			&sync_pos, 
			FRAME_LENGTH_COMPLEX_SAMPLES, 
			768, 
			CHSCH, 
			0);

	// Forcing sync to 0 since were running offline
	if (be_verbose)
		msg ("sync_pos = %d\n", sync_pos);
	PHY_vars->rx_vars[0].offset = 0;	//sync_pos;
	
	// estamte the signal and noise energy
	for (ii=0; ii < NB_ANTENNAS; ii++)
	{
		rx_energy[ii] = signal_energy((int *)&PHY_vars->rx_vars[ii].RX_DMA_BUFFER[PHY_vars->rx_vars[0].offset+CYCLIC_PREFIX_LENGTH],
																	OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES);
		n0_energy[ii] = signal_energy((int *)&PHY_vars->rx_vars[ii].RX_DMA_BUFFER[PHY_vars->rx_vars[0].offset+CYCLIC_PREFIX_LENGTH + 
																	(NUMBER_OF_CHSCH_SYMBOLS+NUMBER_OF_CHBCH_SYMBOLS+1) * OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES],
																	OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES);
		//msg("CYCLIC_PREFIX_LENGTH=%d, NUMBER_OF_CHSCH_SYMBOLS=%d, NUMBER_OF_CHBCH_SYMBOLS=%d, OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES=%d\n", CYCLIC_PREFIX_LENGTH, NUMBER_OF_CHSCH_SYMBOLS, NUMBER_OF_CHBCH_SYMBOLS, OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES);
		msg("symbol = %d\n", PHY_vars->rx_vars[ii].RX_DMA_BUFFER[PHY_vars->rx_vars[0].offset+CYCLIC_PREFIX_LENGTH + 
				(NUMBER_OF_CHSCH_SYMBOLS+NUMBER_OF_CHBCH_SYMBOLS) * OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES]);
		msg("SNR Ant %d = %d / %d \n", ii, rx_energy[ii], n0_energy[ii]);
	}	

	// CHBCH channel estimation
	phy_channel_estimation_top(PHY_vars->rx_vars[0].offset,0,0,0,NB_ANTENNAS,0);
	//phy_channel_estimation_top (PHY_vars->rx_vars[0].offset, 0, 0, 0);

	phy_decode_chbch (0, &dummy_mac_pdu[0], NB_ANTENNAS, NB_ANTENNAS_TX, 120);

	if (be_verbose)
	{
		for (i = 0; i < chbch_size; i++)
		{
			msg ("Data %x : %x\n", i, PHY_vars->chbch_data[0].demod_pdu[i]);
		}
	}
	
	printf("PERROR_SHIFT: %d\n", PERROR_SHIFT);
	
	//
	// Channel estimation procedure
	//
// 	for (i = 0; i < max_num_ofdm_sym; i++)
// 	{
// 		phy_channel_estimation_top(PHY_vars->rx_vars[0].offset,i,0,0,1);
// 	}
	  
	phy_channel_est_emos(16, 16, max_num_ofdm_sym-1, TRUE, 0);

	phy_cleanup ();
	if (be_verbose)
		printf ("Exiting\n");

}
void multipath_channel(channel_desc_t *desc,
                       double **tx_sig_re,
                       double **tx_sig_im,
                       double **rx_sig_re,
                       double **rx_sig_im,
                       uint32_t length,
                       uint8_t keep_channel)
{

  int i,ii,j,l;
  struct complex rx_tmp,tx;

  double path_loss = pow(10,desc->path_loss_dB/20);
  int dd;
  dd = abs(desc->channel_offset);

#ifdef DEBUG_CH
  printf("[CHANNEL] keep = %d : path_loss = %g (%f), nb_rx %d, nb_tx %d, dd %d, len %d \n",keep_channel,path_loss,desc->path_loss_dB,desc->nb_rx,desc->nb_tx,dd,desc->channel_length);
#endif

  if (keep_channel) {
    // do nothing - keep channel
  } else {
    random_channel(desc,0);
  }

#ifdef DEBUG_CH

  for (l = 0; l<(int)desc->channel_length; l++) {
    printf("%p (%f,%f) ",desc->ch[0],desc->ch[0][l].x,desc->ch[0][l].y);
  }

  printf("\n");
#endif

  for (i=0; i<((int)length-dd); i++) {
    for (ii=0; ii<desc->nb_rx; ii++) {
      rx_tmp.x = 0;
      rx_tmp.y = 0;

      for (j=0; j<desc->nb_tx; j++) {
        for (l = 0; l<(int)desc->channel_length; l++) {
          if ((i>=0) && (i-l)>=0) {
            tx.x = tx_sig_re[j][i-l];
            tx.y = tx_sig_im[j][i-l];
          } else {
            tx.x =0;
            tx.y =0;
          }

          rx_tmp.x += (tx.x * desc->ch[ii+(j*desc->nb_rx)][l].x) - (tx.y * desc->ch[ii+(j*desc->nb_rx)][l].y);
          rx_tmp.y += (tx.y * desc->ch[ii+(j*desc->nb_rx)][l].x) + (tx.x * desc->ch[ii+(j*desc->nb_rx)][l].y);
        } //l
      }  // j

      rx_sig_re[ii][i+dd] = rx_tmp.x*path_loss;
      rx_sig_im[ii][i+dd] = rx_tmp.y*path_loss;
      /*
      if ((ii==0)&&((i%32)==0)) {
      printf("%p %p %f,%f => %e,%e\n",rx_sig_re[ii],rx_sig_im[ii],rx_tmp.x,rx_tmp.y,rx_sig_re[ii][i-dd],rx_sig_im[ii][i-dd]);
      }
      */
      //rx_sig_re[ii][i] = sqrt(.5)*(tx_sig_re[0][i] + tx_sig_re[1][i]);
      //rx_sig_im[ii][i] = sqrt(.5)*(tx_sig_im[0][i] + tx_sig_im[1][i]);

    } // ii
  } // i
}
예제 #5
0
int main()
{
    int enb_count = 16;
    int ue_count = 50;
    double sect_angle[3]= {0,2*PI/3,4*PI/3};
    double gain_max;
    double theta;
    double min_path_loss = 0;
    int att_enb_index;
    node_desc_t *enb_data[enb_count];
    node_desc_t *ue_data[ue_count];
    channel_desc_t *ul_channel[ue_count][enb_count];
    channel_desc_t *dl_channel[ue_count][enb_count];
    int count;
    int mcs;
    int ue_index, enb_index;
    int return_value;
    int nb_rb = 25; //No. of resource blocks
    double sinr[enb_count][2*nb_rb];
    double sinr_eff[ue_count][MCS_COUNT];
    double bler[ue_count][MCS_COUNT];
    double gain_sec[3];
    double thermal_noise;
    double interference;
    double coupling;
    FILE *fp;
    char buffer[100];
    char *sinr_bler;
    double tlu_sinr;
    double tlu_bler;
    int line_num;
    char *file_name[]= {"bler_1.csv", "bler_2.csv", "bler_3.csv", "bler_4.csv", "bler_5.csv", "bler_6.csv", "bler_7.csv", "bler_8.csv",
                        "bler_9.csv", "bler_10.csv", "bler_11.csv", "bler_12.csv", "bler_13.csv", "bler_14.csv", "bler_15.csv", "bler_16.csv",
                        "bler_17.csv", "bler_18.csv", "bler_19.csv", "bler_20.csv", "bler_21.csv", "bler_22.csv"
                       };

    double beta[MCS_COUNT] = {0, 0, 0, 0, 0.9459960937499999, 1.2912109374999994, 1.0133789062499998, 1.000390625,
                              1.02392578125, 1.8595703124999998, 2.424389648437498, 2.3946533203124982, 2.5790039062499988,
                              2.4084960937499984, 2.782617187499999, 2.7868652343749996, 3.92099609375, 4.0392578125,
                              4.56109619140625, 5.03338623046875, 5.810888671875, 6.449108886718749
                             };

    double enb_position[][2] = {{1100,1100},{1100,2100},{1100,3100},{1100,4100},
        {2100,1100},{2100,2100},{2100,3100},{2100,4100},
        {3100,1100},{3100,2100},{3100,3100},{3100,4100},
        {4100,1100},{4100,2100},{4100,3100},{4100,4100}
    };

    double ue_position[][2] = {{3340,4740},{1500,620},{1780,4220},{1300,3540},{780,3100},
        {1140,540},{1340,3660},{860,1220},{2700,2140},{3860,3060},
        {3740,1060},{1700,3060},{2180,1620},{4420,1060},{1300,3340},
        {3700,3180},{3780,540},{1700,4380},{4140,4740},{820,4380},
        {3300,1540},{2100,1780},{1780,2260},{1940,2620},{1580,1700},
        {1460,1940},{940,1340},{2100,3540},{1260,4340},{2940,4060},
        {3980,940},{540,2220},{3060,2140},{4620,3940},{4260,2820},
        {3860,3500},{4140,4140},{3900,3500},{1500,2140},{2620,3820},
        {3420,2820},{1580,3940},{660,2100},{2740,1180},{2500,2500},
        {3580,3580},{3740,3140},{3020,3020},{4340,4140},{980,4300}
    };

    randominit(0);

    /////////////////////////////////////////////////////////////////////////////////////////////////
    int tabl_len=0;
    double local_table[MCS_COUNT][9][9];

    for (mcs = 5; mcs <= MCS_COUNT; mcs++) {

        fp = fopen(file_name[mcs - 1],"r");

        if (fp == NULL) {
            printf("ERROR: Unable to open the file\n");
        } else {
            fgets(buffer, 100, fp);
            tabl_len=0;

            while (!feof(fp)) {

                sinr_bler = strtok(buffer, ";");
                local_table[mcs-1][0][tabl_len] = atof(sinr_bler);
                sinr_bler = strtok(NULL,";");
                local_table[mcs-1][1][tabl_len] = atof(sinr_bler);
                tabl_len++;
                fgets(buffer, 100, fp);
            }

            fclose(fp);
        }

        printf("\n table for mcs %d\n",mcs);

        for (tabl_len=0; tabl_len<9; tabl_len++)
            printf("%lf  %lf \n ",local_table[mcs-1][0][tabl_len],local_table[mcs-1][1][tabl_len]);


    }



    ////////////////////////////////////////////////////////////////////////////////////////////////////

    for (enb_index = 0; enb_index < enb_count; enb_index++)
        enb_data[enb_index] = (node_desc_t *)(malloc(sizeof(node_desc_t)));

    for (ue_index = 0; ue_index < ue_count; ue_index++)
        ue_data[ue_index] = (node_desc_t *)(malloc(sizeof(node_desc_t)));

    for (enb_index = 0; enb_index < enb_count; enb_index++)  {
        enb_data[enb_index]->x = enb_position[enb_index][0];
        enb_data[enb_index]->y = enb_position[enb_index][1];
        enb_data[enb_index]->tx_power_dBm = 40;
        enb_data[enb_index]->ant_gain_dBi = 15;
        enb_data[enb_index]->rx_noise_level = 5; //value in db
        enb_data[enb_index]->n_sectors = 3;
    }

    for (ue_index = 0; ue_index < ue_count; ue_index++)  {
        ue_data[ue_index]->x = ue_position[ue_index][0];
        ue_data[ue_index]->y = ue_position[ue_index][1];
        ue_data[ue_index]->phi_rad = 2 * PI;
        ue_data[ue_index]->tx_power_dBm = 20;
        ue_data[ue_index]->ant_gain_dBi = 0;
        ue_data[ue_index]->rx_noise_level = 9; //value in db
    }

    for (ue_index = 0; ue_index < ue_count; ue_index++) {
        min_path_loss = 10000;

        for (enb_index = 0; enb_index < enb_count; enb_index++) {
            ul_channel[ue_index][enb_index] = new_channel_desc_scm(1, 1, SCM_C, 7.68, 0, 0, 0);
            dl_channel[ue_index][enb_index] = new_channel_desc_scm(1, 1, SCM_C, 7.68, 0, 0, 0);
            //printf("ue %d enb %d\n", ue_index, enb_index);

            /* Calculating the angle in the range -pi to pi from the slope */
            //(ue_data[ue_index])->alpha_rad[enb_index] = (double)(atan2((ue_data[ue_index]->x - enb_data[enb_index]->x), (ue_data[ue_index]->y - enb_data[enb_index]->y)));
            ue_data[ue_index]->alpha_rad[enb_index] = atan2((ue_data[ue_index]->x - enb_data[enb_index]->x), (ue_data[ue_index]->y - enb_data[enb_index]->y));
            //printf("angle is tan %lf\n", ue_data[ue_index]->alpha_rad[enb_index]);

            if ((ue_data[ue_index]->alpha_rad[enb_index]) < 0) {
                ue_data[ue_index]->alpha_rad[enb_index] = 2*PI + ue_data[ue_index]->alpha_rad[enb_index];
                //printf("angle in radians is %lf\n", ue_data[ue_index]->alpha_rad[enb_index]);
            }

            for(count = 0; count < enb_data[enb_index]->n_sectors; count++) {
                theta = sect_angle[count] - ue_data[ue_index]->alpha_rad[enb_index];
                gain_sec[count] = -(Am < (12 * pow((theta/theta_3dB),2)) ? Am : (12 * pow((theta/theta_3dB),2)));
            }

            /* gain = -min(Am , 12 * (theta/theta_3dB)^2) */
            gain_max = (gain_sec[SEC1] > gain_sec[SEC2]) ? ((gain_sec[SEC1] > gain_sec[SEC3]) ? gain_sec[SEC1]:gain_sec[SEC3]) :
                       ((gain_sec[SEC2] > gain_sec[SEC3]) ? gain_sec[SEC2]:gain_sec[SEC3]);

            get_chan_desc(enb_data[enb_index], ue_data[ue_index], ul_channel[ue_index][enb_index], &scenario);
            get_chan_desc(enb_data[enb_index], ue_data[ue_index], dl_channel[ue_index][enb_index], &scenario);

            //printf("Path loss for link between ue %d and enb %d is %lf and gain is %lf \n", ue_index, enb_index, dl_channel[ue_index][enb_index]->path_loss_dB, gain_max);

            if (dl_channel[ue_index][enb_index]->path_loss_dB < min_path_loss) {
                min_path_loss = dl_channel[ue_index][enb_index]->path_loss_dB;
                att_enb_index = enb_index;
            }

            //return_value = random_channel(ul_channel[ue_index][enb_index]);
            return_value = random_channel(dl_channel[ue_index][enb_index]);

            /* Thermal noise is calculated using 10log10(K*T*B) K = Boltzmann´s constant T = room temperature B = bandwidth */
            /* Taken as constant for the time being since the BW is not changing */
            thermal_noise = -105; //value in dBm

            if (0 == return_value) {
                //freq_channel(ul_channel[ue_index][enb_index], nb_rb);
                freq_channel(dl_channel[ue_index][enb_index], nb_rb);
                coupling = MCL > (dl_channel[ue_index][enb_index]->path_loss_dB-(enb_data[enb_index]->ant_gain_dBi + gain_max)) ?
                           MCL : (dl_channel[ue_index][enb_index]->path_loss_dB-(enb_data[enb_index]->ant_gain_dBi + gain_max));

                //printf ("coupling factor is %lf\n", coupling);
                for (count = 0; count < (2 * nb_rb); count++) {
                    sinr[enb_index][count] = enb_data[enb_index]->tx_power_dBm
                                             - coupling
                                             - (thermal_noise + ue_data[ue_index]->rx_noise_level)
                                             + 10 * log10 (pow(dl_channel[ue_index][enb_index]->chF[0][count].r, 2)
                                                           + pow(dl_channel[ue_index][enb_index]->chF[0][count].i, 2));

                    //printf("Dl_link SNR for res. block %d is %lf\n", count, sinr[enb_index][count]);
                }
            }
        }

        for (count = 0; count < 2 * nb_rb; count++) {
            interference = 0;

            for (enb_index = 0; enb_index < enb_count; enb_index++) {
                if (att_enb_index != enb_index) {
                    interference += pow(10, 0.1 * sinr[enb_index][count]);
                }
            }

            sinr[att_enb_index][count] -= 10*log10(1 + interference);

            //printf("***Dl_link SINR for res. block %d is %lf\n", count, sinr[att_enb_index][count]);

            for (mcs = 5; mcs <= MCS_COUNT; mcs++) {
                sinr_eff[ue_index][mcs-1] += exp(-(pow(10, (sinr[att_enb_index][count])/10))/beta[mcs-1]);
                //printf("Effective snr   %lf\n",sinr_eff[ue_index][mcs-1]);
                //sinr_eff[ue_index][mcs] += exp(-(sinr[att_enb_index][count])/beta[mcs]);
            }
        }

        for (mcs = 5; mcs <= MCS_COUNT; mcs++) {
            //printf("mcs value  %d \n",mcs);
            //printf("beta value  %lf \n",-beta[mcs-1]);
            //printf("snr_eff value  %lf \n",log(sinr_eff[ue_index][mcs-1]));

            sinr_eff[ue_index][mcs-1] =  -beta[mcs-1] *log((sinr_eff[ue_index][mcs-1])/(2*nb_rb));//
            //printf("snr_eff value  %lf \n",sinr_eff[ue_index][mcs-1]);
            sinr_eff[ue_index][mcs-1] = 10 * log10(sinr_eff[ue_index][mcs-1]);
            sinr_eff[ue_index][mcs-1] *= 10;
            sinr_eff[ue_index][mcs-1] = floor(sinr_eff[ue_index][mcs-1]);

            if ((int)sinr_eff[ue_index][mcs-1]%2) {
                sinr_eff[ue_index][mcs-1] += 1;
            }

            sinr_eff[ue_index][mcs-1] /= 10;

            //printf("Effective snr   %lf  \n",sinr_eff[ue_index][mcs-1]);

            bler[ue_index][mcs-1] = 0;

            /*line_num = 0;
            fp = fopen(file_name[mcs - 1],"r");
            if (fp == NULL) {
              printf("ERROR: Unable to open the file\n");
            }
            else {
              fgets(buffer, 100, fp);
              while (!feof(fp)) {
            line_num++;
            sinr_bler = strtok(buffer, ";");
            tlu_sinr = atof(sinr_bler);
            sinr_bler = strtok(NULL,";");
            tlu_bler = atof(sinr_bler);
            if (1 == line_num) {
            if (sinr_eff[ue_index][mcs-1] < tlu_sinr) {
            bler[ue_index][mcs-1] = 1;
            break;
            }
            }
            if (sinr_eff[ue_index][mcs-1] == tlu_sinr) {
            bler[ue_index][mcs-1] = tlu_bler;
            }
            fgets(buffer, 100, fp);
              }
              fclose(fp);*/
            for (tabl_len=0; tabl_len<9; tabl_len++) {

                if(tabl_len==0)
                    if (sinr_eff[ue_index][mcs-1] < local_table[mcs-1][0][tabl_len]) {
                        bler[ue_index][mcs-1] = 1;
                        break;
                    }


                if (sinr_eff[ue_index][mcs-1] == local_table[mcs-1][0][tabl_len]) {
                    bler[ue_index][mcs-1] = local_table[mcs-1][1][tabl_len];
                }

            }

            //printf("\n###Dl_link UE %d attached to eNB %d \n MCS %d effective SNR %lf BLER %lf", ue_index, att_enb_index, mcs,sinr_eff[ue_index][mcs-1],bler[ue_index][mcs-1]);
        }

        //printf("\n\n");

        printf("\n     Ue_ix enb_ix  mcs5    mcs6    mcs7    mcs8    mcs9   mcs10   mcs11   mcs12   mcs13\
   mcs14   mcs15   mcs16   mcs17   mcs18   mcs19   mcs20   mcs21   mcs22\n");

        printf("SINR %4d   %4d  %+4.2f   %+4.2f   %+4.2f   %+4.2f   %+4.2f   %+4.2f   %+4.2f   %+4.2f\
   %+4.2f   %+4.2f   %+4.2f   %+4.2f   %+4.2f   %+4.2f   %+4.2f   %+4.2f   %+4.2f   %+4.2f\n",
               ue_index, att_enb_index, sinr_eff[ue_index][4], sinr_eff[ue_index][5], sinr_eff[ue_index][6], sinr_eff[ue_index][7],
               sinr_eff[ue_index][8], sinr_eff[ue_index][9], sinr_eff[ue_index][10], sinr_eff[ue_index][11], sinr_eff[ue_index][12],
               sinr_eff[ue_index][13], sinr_eff[ue_index][14], sinr_eff[ue_index][15], sinr_eff[ue_index][16], sinr_eff[ue_index][17],
               sinr_eff[ue_index][18], sinr_eff[ue_index][19], sinr_eff[ue_index][20], sinr_eff[ue_index][21], sinr_eff[ue_index][22]);

        printf("BLER %4d   %4d  %+4.2f   %+4.2f   %+4.2f   %+4.2f   %+4.2f   %+4.2f   %+4.2f   %+4.2f\
   %+4.2f   %+4.2f   %+4.2f   %+4.2f   %+4.2f   %+4.2f   %+4.2f   %+4.2f   %+4.2f   %+4.2f\n",
               ue_index, att_enb_index, bler[ue_index][4], bler[ue_index][5], bler[ue_index][6], bler[ue_index][7],
               bler[ue_index][8], bler[ue_index][9], bler[ue_index][10], bler[ue_index][11], bler[ue_index][12],
               bler[ue_index][13], bler[ue_index][14], bler[ue_index][15], bler[ue_index][16], bler[ue_index][17],
               bler[ue_index][18], bler[ue_index][19], bler[ue_index][20], bler[ue_index][21], bler[ue_index][22]);
    }
}