/*******************************************************************************

*******************************************************************************/
/*! \file PHY/LTE_TRANSPORT/dci_NB_IoT.c
* \brief Top-level routines for implementing Tail-biting convolutional coding for transport channels (NPDCCH) for NB_IoT,	 TS 36-212, V13.4.0 2017-02
* \author M. KANJ
* \date 2017
* \version 0.0
* \company bcom
* \email: matthieu.kanj@b-com.com
* \note
* \warning
*/

#ifdef USER_MODE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#endif
#include "PHY/defs.h"
#include "PHY/extern.h"
#include "SCHED/defs.h"
#include "SIMULATION/TOOLS/defs.h"
#include "PHY/sse_intrin.h"

#include "assertions.h" 
#include "T.h"

static uint8_t d[2][3*(MAX_DCI_SIZE_BITS_NB_IOT + 16) + 96];
static uint8_t w[2][3*3*(MAX_DCI_SIZE_BITS_NB_IOT+16)];


void dci_encoding_NB_IoT(uint8_t *a[2],				// Table of two DCI, even if one DCI is to transmit , the number of DCI is indicated in dci_number
						uint8_t A,					// Length of table a
						uint16_t E,					// E should equals to G (number of available bits in one RB)
						uint8_t *e[2],				// *e should be e[2][G]
						uint16_t rnti[2],			// RNTI for UE specific or common search space
						uint8_t dci_number,			// This variable should takes the 1 or 2 (1 for in case of one DCI, 2 in case of two DCI)
						uint8_t agr_level)			// Aggregation level	
{
	uint8_t D = (A + 16);
	uint32_t RCC;
	uint8_t occupation_size=1;
	// encode dci
	if(dci_number == 1)
	{
		if(agr_level == 2)
		{
			occupation_size=1;
		}else{
			occupation_size=2;
		}
		memset((void *)d[0],LTE_NULL,96);
  
		ccode_encode_NB_IoT(A,2,a[0],d[0]+96,rnti[0]);    					// CRC attachement & Tail-biting convolutional coding
		RCC = sub_block_interleaving_cc_NB_IoT(D,d[0]+96,w[0]);				// Interleaving
		lte_rate_matching_cc_NB_IoT(RCC,(E/occupation_size),w[0],e[0]);		// Rate Matching
		
	}else if (dci_number == 2) {
		
		memset((void *)d[0],LTE_NULL,96);
		memset((void *)d[1],LTE_NULL,96);
		// first DCI encoding
		ccode_encode_NB_IoT(A,2,a[0],d[0]+96,rnti[0]);    					// CRC attachement & Tail-biting convolutional coding
		RCC = sub_block_interleaving_cc_NB_IoT(D,d[0]+96,w[0]);				// interleaving
		lte_rate_matching_cc_NB_IoT(RCC,E/2,w[0],e[0]);						// Rate Matching , E/2 ,  NCCE0
		// second DCI encoding
		ccode_encode_NB_IoT(A,2,a[1],d[1]+96,rnti[1]);    					// CRC attachement & Tail-biting convolutional coding
		RCC = sub_block_interleaving_cc_NB_IoT(D,d[1]+96,w[1]);				// Interleaving
		lte_rate_matching_cc_NB_IoT(RCC,E/2,w[1],e[1]);						// Rate Matching, E/2 , NCCE1
		
	}
}

///The scrambling sequence shall be initialised at the start of the search space and after every 4th NPDCCH subframes.
///
///
void npdcch_scrambling_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms,
							  uint8_t *e[2],							// Input data
							  int length,        						// Total number of bits to transmit in one subframe(case of DCI = G)
							  uint8_t Ns,								// Slot number (0..19)
							  uint8_t dci_number,						// This variable should takes the 1 or 2 (1 for in case of one DCI, 2 in case of two DCI)
							  uint8_t agr_level)						// Aggregation level							
{
	int i,j,k=0;
	uint32_t x1, x2, s=0;
	uint8_t reset;
	reset = 1;
	uint8_t occupation_size=1;
	
	if(agr_level == 2)
	{
		occupation_size=1;
	}else{
		occupation_size=2;
	}

	if(dci_number == 1)														// Case of one DCI
	{
		x2 = ((Ns>>1)<<9) + frame_parms->Nid_cell;                          // This is c_init in 36.211 Sec 10.2.3.1
		
		for (i=0; i<length/occupation_size; i++) {
			if ((i&0x1f)==0) {
				s = lte_gold_generic_NB_IoT(&x1, &x2, reset);
				reset = 0;
			}
			e[0][k] = (e[0][k]&1) ^ ((s>>(i&0x1f))&1);
		}
		
	}else if(dci_number == 2 && occupation_size == 2) {						// Case of two DCI
		
		// Scrambling the first DCI
		//
		x2 = ((Ns>>1)<<9) + frame_parms->Nid_cell;                          // This is c_init in 36.211 Sec 10.2.3.1
  
		for (i=0; i<length/occupation_size; i++) {
			if ((i&0x1f)==0) {
				s = lte_gold_generic_NB_IoT(&x1, &x2, reset);
				reset = 0;
			}
			e[0][k] = (e[0][k]&1) ^ ((s>>(i&0x1f))&1);
		}
		// reset of the scrambling function
		reset = 1;
		// Scrambling the second DCI
		//
		x2 = ((Ns>>1)<<9) + frame_parms->Nid_cell;                          //this is c_init in 36.211 Sec 10.2.3.1
  
		for (i=0; i<length/occupation_size; i++) {
			if ((i&0x1f)==0) {
				s = lte_gold_generic_NB_IoT(&x1, &x2, reset);
				reset = 0;
			}
			e[1][k] = (e[1][k]&1) ^ ((s>>(i&0x1f))&1);
		}
	}
}


int dci_allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms,
                                  int32_t **txdataF,
                                  uint32_t *jj,
                                  uint32_t symbol_offset,
                                  uint8_t *x0[2],
                                  uint8_t pilots,
                                  int16_t amp,
						  	      unsigned short id_offset,
                                  uint32_t *re_allocated, 								//  not used variable ??!!
								  uint8_t dci_number,									// This variable should takes the 1 or 2 (1 for in case of one DCI, 2 in case of two DCI)
								  uint8_t agr_level) 
{
	MIMO_mode_t mimo_mode = (frame_parms->mode1_flag==1)?SISO:ALAMOUTI;
	uint32_t tti_offset,aa;
	uint8_t re, diff_re;
	int16_t gain_lin_QPSK;
	uint8_t first_re,last_re;
	int32_t tmp_sample1,tmp_sample2,tmp_sample3,tmp_sample4;
	gain_lin_QPSK = (int16_t)((amp*ONE_OVER_SQRT2_Q15)>>15);
	first_re=0;
	last_re=12;
  
	if(agr_level == 2 && dci_number == 1)
	{
		for (re=first_re; re<last_re; re++) {      		// re varies between 0 and 12 sub-carriers

			tti_offset = symbol_offset + re;				// symbol_offset = 512 * L ,  re_offset = 512 - 3*12  , re
	
			if (pilots != 1 || re%3 != id_offset)  			// if re is not a pilot
			{
													//	diff_re = re%3 - id_offset;  
				if (mimo_mode == SISO) {  								//SISO mapping
					*re_allocated = *re_allocated + 1;						// variable incremented but never used
			
					for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
						((int16_t*)&txdataF[aa][tti_offset])[0] += (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
					}
					*jj = *jj + 1;
					for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
						((int16_t*)&txdataF[aa][tti_offset])[1] += (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
					}
					*jj = *jj + 1;	
			
			} else if (mimo_mode == ALAMOUTI) {
	  
				*re_allocated = *re_allocated + 1;

				((int16_t*)&tmp_sample1)[0] = (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
				*jj=*jj+1;
				((int16_t*)&tmp_sample1)[1] = (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
				*jj=*jj+1;

				// second antenna position n -> -x1*

				((int16_t*)&tmp_sample2)[0] = (x0[0][*jj]==1) ? (gain_lin_QPSK) : -gain_lin_QPSK;
				*jj=*jj+1;
				((int16_t*)&tmp_sample2)[1] = (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
				*jj=*jj+1;

				// normalization for 2 tx antennas
				((int16_t*)&txdataF[0][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0]*ONE_OVER_SQRT2_Q15)>>15);
				((int16_t*)&txdataF[0][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*ONE_OVER_SQRT2_Q15)>>15);
				((int16_t*)&txdataF[1][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample2)[0]*ONE_OVER_SQRT2_Q15)>>15);
				((int16_t*)&txdataF[1][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample2)[1]*ONE_OVER_SQRT2_Q15)>>15);
	
				// fill in the rest of the ALAMOUTI precoding
				if ( pilots != 1 || (re+1)%3 != id_offset) {
					((int16_t *)&txdataF[0][tti_offset+1])[0] += -((int16_t *)&txdataF[1][tti_offset])[0]; //x1
					((int16_t *)&txdataF[0][tti_offset+1])[1] += ((int16_t *)&txdataF[1][tti_offset])[1];
					((int16_t *)&txdataF[1][tti_offset+1])[0] += ((int16_t *)&txdataF[0][tti_offset])[0];  //x0*
					((int16_t *)&txdataF[1][tti_offset+1])[1] += -((int16_t *)&txdataF[0][tti_offset])[1];
				} else {
					((int16_t *)&txdataF[0][tti_offset+2])[0] += -((int16_t *)&txdataF[1][tti_offset])[0]; //x1
					((int16_t *)&txdataF[0][tti_offset+2])[1] += ((int16_t *)&txdataF[1][tti_offset])[1];
					((int16_t *)&txdataF[1][tti_offset+2])[0] += ((int16_t *)&txdataF[0][tti_offset])[0];  //x0*
					((int16_t *)&txdataF[1][tti_offset+2])[1] += -((int16_t *)&txdataF[0][tti_offset])[1];
		
					re++;														// skip pilots
					*re_allocated = *re_allocated + 1;
				}
				re++;  															// adjacent carriers are taken care of by precoding
				*re_allocated = *re_allocated + 1;   							// incremented variable but never used
			}	
		}
	}
  }else if(agr_level == 1 && dci_number == 1){
	for (re=first_re; re<6; re++) {      		// re varies between 0 and 6 sub-carriers

    tti_offset = symbol_offset + re;				// symbol_offset = 512 * L ,  re_offset = 512 - 3*12  , re
	
	if (pilots != 1 || re%3 != id_offset)  			// if re is not a pilot
	{
													//	diff_re = re%3 - id_offset;  
		if (mimo_mode == SISO) {  								//SISO mapping
			*re_allocated = *re_allocated + 1;						// variable incremented but never used
			
			for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
					((int16_t*)&txdataF[aa][tti_offset])[0] += (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
			}
			*jj = *jj + 1;
			for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
				((int16_t*)&txdataF[aa][tti_offset])[1] += (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
			}
			*jj = *jj + 1;	
			
		} else if (mimo_mode == ALAMOUTI) {
	  
			*re_allocated = *re_allocated + 1;

			((int16_t*)&tmp_sample1)[0] = (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
			*jj=*jj+1;
			((int16_t*)&tmp_sample1)[1] = (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
			*jj=*jj+1;

			// second antenna position n -> -x1*

			((int16_t*)&tmp_sample2)[0] = (x0[0][*jj]==1) ? (gain_lin_QPSK) : -gain_lin_QPSK;
			*jj=*jj+1;
			((int16_t*)&tmp_sample2)[1] = (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
			*jj=*jj+1;

			// normalization for 2 tx antennas
			((int16_t*)&txdataF[0][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0]*ONE_OVER_SQRT2_Q15)>>15);
			((int16_t*)&txdataF[0][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*ONE_OVER_SQRT2_Q15)>>15);
			((int16_t*)&txdataF[1][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample2)[0]*ONE_OVER_SQRT2_Q15)>>15);
			((int16_t*)&txdataF[1][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample2)[1]*ONE_OVER_SQRT2_Q15)>>15);

			// fill in the rest of the ALAMOUTI precoding
			if ( pilots != 1 || (re+1)%3 != id_offset) {
				((int16_t *)&txdataF[0][tti_offset+1])[0] += -((int16_t *)&txdataF[1][tti_offset])[0]; //x1
				((int16_t *)&txdataF[0][tti_offset+1])[1] += ((int16_t *)&txdataF[1][tti_offset])[1];
				((int16_t *)&txdataF[1][tti_offset+1])[0] += ((int16_t *)&txdataF[0][tti_offset])[0];  //x0*
				((int16_t *)&txdataF[1][tti_offset+1])[1] += -((int16_t *)&txdataF[0][tti_offset])[1];
			} else {
				((int16_t *)&txdataF[0][tti_offset+2])[0] += -((int16_t *)&txdataF[1][tti_offset])[0]; //x1
				((int16_t *)&txdataF[0][tti_offset+2])[1] += ((int16_t *)&txdataF[1][tti_offset])[1];
				((int16_t *)&txdataF[1][tti_offset+2])[0] += ((int16_t *)&txdataF[0][tti_offset])[0];  //x0*
				((int16_t *)&txdataF[1][tti_offset+2])[1] += -((int16_t *)&txdataF[0][tti_offset])[1];
		
				re++;														// skip pilots
				*re_allocated = *re_allocated + 1;
			}
			re++;  															// adjacent carriers are taken care of by precoding
			*re_allocated = *re_allocated + 1;   							// incremented variable but never used
		 }
     }
   }
  } else {
	
	// allocate first DCI
	for (re=first_re; re<6; re++) {      		// re varies between 0 and 12 sub-carriers

    tti_offset = symbol_offset + re;				// symbol_offset = 512 * L ,  re_offset = 512 - 3*12  , re
	
	if (pilots != 1 || re%3 != id_offset)  			// if re is not a pilot
	{
													//	diff_re = re%3 - id_offset;  
      if (mimo_mode == SISO) {  								//SISO mapping
			*re_allocated = *re_allocated + 1;						// variable incremented but never used
			
			for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
				((int16_t*)&txdataF[aa][tti_offset])[0] += (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
				((int16_t*)&txdataF[aa][tti_offset+6])[0] += (x0[1][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
			}
			*jj = *jj + 1;
			for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
				((int16_t*)&txdataF[aa][tti_offset])[1] += (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
				((int16_t*)&txdataF[aa][tti_offset+6])[1] += (x0[1][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
			}
			*jj = *jj + 1;	
			
      } else if (mimo_mode == ALAMOUTI) {
	  
			*re_allocated = *re_allocated + 1;

			((int16_t*)&tmp_sample1)[0] = (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
			((int16_t*)&tmp_sample3)[0] = (x0[1][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
			*jj=*jj+1;
			((int16_t*)&tmp_sample1)[1] = (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
			((int16_t*)&tmp_sample3)[1] = (x0[1][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
			*jj=*jj+1;

			// second antenna position n -> -x1*

			((int16_t*)&tmp_sample2)[0] = (x0[0][*jj]==1) ? (gain_lin_QPSK) : -gain_lin_QPSK;
			((int16_t*)&tmp_sample4)[0] = (x0[1][*jj]==1) ? (gain_lin_QPSK) : -gain_lin_QPSK;
			*jj=*jj+1;
			((int16_t*)&tmp_sample2)[1] = (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
			((int16_t*)&tmp_sample4)[1] = (x0[1][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
			*jj=*jj+1;

			// normalization for 2 tx antennas
			((int16_t*)&txdataF[0][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0]*ONE_OVER_SQRT2_Q15)>>15);
			((int16_t*)&txdataF[0][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*ONE_OVER_SQRT2_Q15)>>15);
			((int16_t*)&txdataF[1][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample2)[0]*ONE_OVER_SQRT2_Q15)>>15);
			((int16_t*)&txdataF[1][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample2)[1]*ONE_OVER_SQRT2_Q15)>>15);
			
			((int16_t*)&txdataF[0][tti_offset+6])[0] += (int16_t)((((int16_t*)&tmp_sample3)[0]*ONE_OVER_SQRT2_Q15)>>15);
			((int16_t*)&txdataF[0][tti_offset+6])[1] += (int16_t)((((int16_t*)&tmp_sample3)[1]*ONE_OVER_SQRT2_Q15)>>15);
			((int16_t*)&txdataF[1][tti_offset+6])[0] += (int16_t)((((int16_t*)&tmp_sample4)[0]*ONE_OVER_SQRT2_Q15)>>15);
			((int16_t*)&txdataF[1][tti_offset+6])[1] += (int16_t)((((int16_t*)&tmp_sample4)[1]*ONE_OVER_SQRT2_Q15)>>15);

			// fill in the rest of the ALAMOUTI precoding
			if ( pilots != 1 || (re+1)%3 != id_offset) {
				((int16_t *)&txdataF[0][tti_offset+1])[0] += -((int16_t *)&txdataF[1][tti_offset])[0]; //x1
				((int16_t *)&txdataF[0][tti_offset+1])[1] += ((int16_t *)&txdataF[1][tti_offset])[1];
				((int16_t *)&txdataF[1][tti_offset+1])[0] += ((int16_t *)&txdataF[0][tti_offset])[0];  //x0*
				((int16_t *)&txdataF[1][tti_offset+1])[1] += -((int16_t *)&txdataF[0][tti_offset])[1];
				
				((int16_t *)&txdataF[0][tti_offset+6+1])[0] += -((int16_t *)&txdataF[1][tti_offset+6])[0]; //x1
				((int16_t *)&txdataF[0][tti_offset+6+1])[1] += ((int16_t *)&txdataF[1][tti_offset+6])[1];
				((int16_t *)&txdataF[1][tti_offset+6+1])[0] += ((int16_t *)&txdataF[0][tti_offset+6])[0];  //x0*
				((int16_t *)&txdataF[1][tti_offset+6+1])[1] += -((int16_t *)&txdataF[0][tti_offset+6])[1];
			} else {
				((int16_t *)&txdataF[0][tti_offset+2])[0] += -((int16_t *)&txdataF[1][tti_offset])[0]; //x1
				((int16_t *)&txdataF[0][tti_offset+2])[1] += ((int16_t *)&txdataF[1][tti_offset])[1];
				((int16_t *)&txdataF[1][tti_offset+2])[0] += ((int16_t *)&txdataF[0][tti_offset])[0];  //x0*
				((int16_t *)&txdataF[1][tti_offset+2])[1] += -((int16_t *)&txdataF[0][tti_offset])[1];
				
				((int16_t *)&txdataF[0][tti_offset+6+2])[0] += -((int16_t *)&txdataF[1][tti_offset+6])[0]; //x1
				((int16_t *)&txdataF[0][tti_offset+6+2])[1] += ((int16_t *)&txdataF[1][tti_offset+6])[1];
				((int16_t *)&txdataF[1][tti_offset+6+2])[0] += ((int16_t *)&txdataF[0][tti_offset+6])[0];  //x0*
				((int16_t *)&txdataF[1][tti_offset+6+2])[1] += -((int16_t *)&txdataF[0][tti_offset+6])[1];
		
				re++;														// skip pilots
				*re_allocated = *re_allocated + 1;
			}
			re++;  															// adjacent carriers are taken care of by precoding
			*re_allocated = *re_allocated + 1;   							// incremented variable but never used
		}
      }
    }
  }
  return(0);
}


int dci_modulation_NB_IoT(int32_t **txdataF,
						int16_t amp,
						NB_IOT_DL_FRAME_PARMS *frame_parms,
						uint8_t control_region_size,                        // control region size for LTE , values between 0..3, (0 for stand-alone / 1, 2 or 3 for in-band)
						uint8_t *e[2],										// Input data
						int G,												// number of bits per subframe		
						unsigned short NB_IoT_RB_ID
						uint8_t dci_number,									// This variable should takes the 1 or 2 (1 for in case of one DCI, 2 in case of two DCI)
						uint8_t agr_level)									// Aggregation level
{
    uint32_t jj=0;
	uint32_t re_allocated,symbol_offset;
    uint16_t l;
    uint8_t id_offset,pilots=0; 
	unsigned short bandwidth_even_odd;
    unsigned short NB_IoT_start, RB_IoT_ID;
    re_allocated=0;
	id_offset=0;
	// testing if the total number of RBs is even or odd 
		bandwidth_even_odd = frame_parms->N_RB_DL % 2; 	 	// 0 even, 1 odd
		RB_IoT_ID = NB_IoT_RB_ID;
	// step  5, 6, 7   									 	// modulation and mapping (slot 1, symbols 0..3)
	for (l=control_region_size; l<14; l++) { 								 	// loop on OFDM symbols	
		if((l>=4 && l<=8) || (l>=11 && l<=13))
		{
			pilots =1;
		} else {
			pilots=0;
		}
		id_offset = frame_parms->Nid_cell % 3;    			// Cell_ID_NB_IoT % 3
		if(RB_IoT_ID < (frame_parms->N_RB_DL/2))
		{
			NB_IoT_start = frame_parms->ofdm_symbol_size - 12*(frame_parms->N_RB_DL/2) - (bandwidth_even_odd*6) + 12*(RB_IoT_ID%(ceil(frame_parms->N_RB_DL/(float)2)));
		} else {
			NB_IoT_start = (bandwidth_even_odd*6) + 12*(RB_IoT_ID%(ceil(frame_parms->N_RB_DL/(float)2)));
		}
		symbol_offset = frame_parms->ofdm_symbol_size*l + NB_IoT_start;  						// symbol_offset = 512 * L + NB_IOT_RB start
		dci_allocate_REs_in_RB_NB_IoT(frame_parms,
								      txdataF,
							    	  &jj,
									  symbol_offset,
									  &e,
									  pilots,
									  amp,
									  id_offset,
									  &re_allocated,
									  dci_number,
									  agr_level);
	}
	
    // VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_MODULATION, VCD_FUNCTION_OUT);
  return (re_allocated);
}





//*******************************************************************************************************
//*******************************************************************************************************
//********************************** Michele code *******************************************************
//*******************************************************************************************************
//*******************************************************************************************************
//*******************************************************************************************************
uint8_t generate_dci_top_NB(uint8_t Num_dci,
                         DCI_ALLOC_NB_t *dci_alloc,
                         int16_t amp,
                         NB_DL_FRAME_PARMS *fp,
                         //NB_IoT_eNB_NPDCCH_t npdcch,
                         int32_t **txdataF,
                         uint32_t subframe)
{


  int i,L, G;
  int npdcch_start_index;

  /* PARAMETERS may not needed
  **e_ptr : store the encoding result, and as a input to modulation
  *num_pdcch_symbols : to calculate the resource allocation for pdcch
  *L = aggregation level (there is 2 (at most) in NB-IoT) (Note this is not the real value but the index)
  *lprime,kprime,kprime_mod12,mprime,nsymb,symbol_offset,tti_offset,re_offset : used in the REG allocation
  *gain_lin_QPSK,yseq0[Msymb],yseq1[Msymb],*y[2] : used in the modulation
  *mi = used in interleaving
  *e = used to store the taus sequence (taus sequence is used to generate the first sequence for DCI) Turbo coding
  *wbar used in the interleaving and also REG allocation
  */

  //num_pdcch_symbols = get_num_pdcch_symbols(num_ue_spec_dci+num_common_dci,dci_alloc,frame_parms,subframe);


  // generate DCIs in order of decreasing aggregation level, then common/ue spec
  // MAC is assumed to have ordered the UE spec DCI according to the RNTI-based randomization???

  // Value of aggregation level (FAPI/NFAPI specs v.9.0 pag 221 value 1,2)
  for (L=2; L>=1; L--) {
    for (i=0; i<Num_dci; i++) {

    	//XXX should be checked how the scheduler store the aggregation level for NB-IoT (value 1-2 or 0-1)
      if (dci_alloc[i].L == (uint8_t)L) {

        if (dci_alloc[i].firstCCE>=0) {


          //NB-IoT encoding
          /*npdcch_encoding_NB_IoT(dci_alloc[i].dci_pdu,
                                 frame_parms,
                                 npdcch, //see when function dci_top is called
                                 //no frame
                                subframe
                                //rm_stats, te_stats, i_stats
                                );*/

        }
      }
    }

  }


  //NB-IoT scrambling
  /*
   *
   * TS 36.213 ch 16.6.1
   * npdcch_start_index  indicate the starting OFDM symbol for NPDCCH in the first slot of a subframe k ad is determined as follow:
   * - if eutracontrolregionsize is present (defined for in-band operating mode (mode 0,1 for FAPI specs))
   * 	npdcch_start_index = eutracontrolregionsize (value 1,2,3) [units in number of OFDM symbol]
   * -otherwise
   * 	npdcch_start_index = 0
   *
   *Depending on npddch_start_index then we define different values for G
   */

  //XXX the setting of this npdcch_start_index parameter should be done in the MAC
//  if(fp->operating_mode == 0 || fp->operating_mode == 1) //in-band operating mode
//  {
//	  npdcch_start_index = fp->control_region_size;
//  }
//  else
//  {
//	  npdcch_start_index = 0;
//  }

  for(int i = 0; i <Num_dci; i++)
  {

	  switch(dci_alloc[i].npdcch_start_symbol) //mail Bcom matthieu
	  {
  	  	  case 0:
  	  		  G = 304;
  		 	break;
  	  	  case 1:
  	  		  G = 240;
  	  		  break;
  	  	  case 2:
  	  		  G = 224;
  	  		  break;
  	  	  case 3:
  	  		  G =200;
  	  		  break;
  	  	  default:
  	  		  LOG_E (PHY,"npdcch_start_index has unwanted value\n");
  	  		  break;
	  }



//  	  	  // NB-IoT scrambling
//  	  	  npdcch_scrambling_NB_IoT(
//  	  	              frame_parms,
//  	  				  npdcch,
//  	  				  //G,
//  	  				  //q = nf mod 2 (TS 36.211 ch 10.2.3.1)  with nf = number of frame
//  	  				  //slot_id
//  	  	                    );


  }



//  //NB-IoT modulation
//  npdcch_modulation_NB_IoT(
//      txdataF,
//      AMP,
//      frame_parms,
//      //no symbol
//      //npdcch0???
//      //RB_ID --> statically get from the higher layer (may included in the dl_frame params)
//      );




  //in NB-IoT the interleaving is done directly with the encoding procedure
  //there is no interleaving because we don't apply turbo coding


  // This is the REG allocation algorithm from 36-211
  //already done in the modulation in our NB-IoT implementaiton??
 
 //*******************************************************************************************************
 //*******************************************************************************************************
 //*******************************************************************************************************
 //*******************************************************************************************************
 //*******************************************************************************************************

  return 0;
}