/*
 * 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.0  (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
 */

/*! \file output_handler_NB_IoT.c
 * \brief Convert MAC scheduler result and output the FAPI structure by subframe based
 * \author  NTUST BMW Lab./
 * \date 2017
 * \email: 
 * \version 1.0
 *
 */

#include "defs_NB_IoT.h"
#include "proto_NB_IoT.h"
#include "extern_NB_IoT.h"
#include "openair2/RRC/LITE/proto_NB_IoT.h"
#include "openair2/PHY_INTERFACE/IF_Module_NB_IoT.h"

int output_handler(eNB_MAC_INST_NB_IoT *mac_inst, module_id_t module_id, int CC_id, uint32_t hypersfn, uint32_t frame, uint32_t subframe, uint8_t MIB_flag, uint8_t SIB1_flag, uint32_t current_time){
	
	uint8_t MIB_size = 0;
	uint8_t SIB1_size = 0, i = 0;

	// to get MIB and SIB
	rrc_eNB_carrier_data_NB_IoT_t *carrier = &eNB_rrc_inst_NB_IoT->carrier[0];
	
	Sched_Rsp_NB_IoT_t *SCHED_info = &mac_inst->Sched_INFO;
	
	nfapi_dl_config_request_pdu_t *dl_config_pdu;
	nfapi_hi_dci0_request_pdu_t* hi_dci0_pdu;
	nfapi_ul_config_request_pdu_t* ul_config_pdu = NULL;
	schedule_result_t *tmp;
	int DL_empty = 0, UL_empty = 0; 
	int flag_malloc = 0 ;

	// filled common part of schedule_resoponse
	SCHED_info->module_id = module_id;
	SCHED_info->hypersfn = hypersfn;
	SCHED_info->frame = frame;
	SCHED_info->subframe = subframe;
	void *DCI_pdu;
         
	// free all the memory allocate to the previous subframe
	if(flag_malloc)
	{
		free(SCHED_info->TX_req->tx_request_body.tx_pdu_list);
	    free(SCHED_info->HI_DCI0_req->hi_dci0_request_body.hi_dci0_pdu_list);
	    free(SCHED_info->DL_req->dl_config_request_body.dl_config_pdu_list);
	    free(SCHED_info->UL_req->ul_config_request_body.ul_config_pdu_list);
	    
	    free(SCHED_info->TX_req);
	    free(SCHED_info->HI_DCI0_req);
	    free(SCHED_info->DL_req);
	    free(SCHED_info->UL_req);
	}

	// allocate the memory for the current output subframe
	SCHED_info->TX_req = (nfapi_tx_request_t *) malloc (sizeof(nfapi_tx_request_t));
	SCHED_info->TX_req->tx_request_body.tx_pdu_list = (nfapi_tx_request_pdu_t *) malloc (sizeof(nfapi_tx_request_pdu_t));
	SCHED_info->UL_req = (nfapi_ul_config_request_t*) malloc (sizeof(nfapi_ul_config_request_t));
  	SCHED_info->UL_req->ul_config_request_body.ul_config_pdu_list = (nfapi_ul_config_request_pdu_t *)malloc(5 * sizeof(nfapi_ul_config_request_pdu_t));
  	SCHED_info->HI_DCI0_req = (nfapi_hi_dci0_request_t*) malloc (sizeof(nfapi_hi_dci0_request_t));
  	SCHED_info->HI_DCI0_req->hi_dci0_request_body.hi_dci0_pdu_list = (nfapi_hi_dci0_request_pdu_t*)malloc(sizeof(nfapi_hi_dci0_request_pdu_t));
	SCHED_info->DL_req = (nfapi_dl_config_request_t*) malloc (sizeof(nfapi_dl_config_request_t));
	SCHED_info->DL_req->dl_config_request_body.dl_config_pdu_list = (nfapi_dl_config_request_pdu_t*)malloc(sizeof(nfapi_dl_config_request_pdu_t));
	flag_malloc = 1;
	
	SCHED_info->DL_req->dl_config_request_body.number_pdu = 0;
  	SCHED_info->UL_req->ul_config_request_body.number_of_pdus = 0;
  	SCHED_info->HI_DCI0_req->hi_dci0_request_body.number_of_dci = 0;
  
  	//	process downlink data transmission, there will only be single DL_REQ in one subframe (e.g. 1ms), check common signal first
	if(subframe == 0) // MIB session
	{
		// get the MIB pdu from carrier (RRC structure)
		uint8_t *MIB_pdu = get_NB_IoT_MIB(carrier,1,subframe,frame,hypersfn);
		// get the size of MIB
		MIB_size = get_NB_IoT_MIB_size();
		dl_config_pdu = SCHED_info->DL_req->dl_config_request_body.dl_config_pdu_list;
    	SCHED_info->DL_req->dl_config_request_body.number_pdu = 1;
		dl_config_pdu->pdu_type                                               	 = NFAPI_DL_CONFIG_NBCH_PDU_TYPE;
  		dl_config_pdu->pdu_size                                               	 = 2+sizeof(nfapi_dl_config_nbch_pdu_rel13_t);
  		dl_config_pdu->nbch_pdu.nbch_pdu_rel13.length                            = MIB_size;
  		dl_config_pdu->nbch_pdu.nbch_pdu_rel13.pdu_index                         = 1;
  		dl_config_pdu->nbch_pdu.nbch_pdu_rel13.transmission_power                = 6000;
  		
  		// fill MIB PDU
  		SCHED_info->TX_req->tx_request_body.tx_pdu_list[dl_config_pdu->nbch_pdu.nbch_pdu_rel13.pdu_index].segments[0].segment_data = MIB_pdu;
  		LOG_D(MAC,"NB-IoT fill MIB\n");
	}
	else if(SIB1_flag==1) // SIB1 flag, calculated by scheduler
	{
		// get SIB1 PDU from carrier and updated by time
		uint8_t *SIB1_pdu = get_NB_IoT_SIB1(0,0,carrier,208,93,1,3584,28,2,subframe,frame,hypersfn);
		// get the size of SIB1
		SIB1_size = get_NB_IoT_SIB1_size();
		dl_config_pdu = SCHED_info->DL_req->dl_config_request_body.dl_config_pdu_list;
		SCHED_info->DL_req->dl_config_request_body.number_pdu = 1;
		dl_config_pdu->pdu_type                                                   = NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE;
		dl_config_pdu->pdu_size                                                   = 2+sizeof(nfapi_dl_config_ndlsch_pdu_rel13_t);
		dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.length                         = SIB1_size;
		dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.pdu_index					  = 1;
		dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.rnti_type                      = 0;
		dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.rnti                           = 0xFFFF; // SI-rnti
		dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.modulation                     = 2;
		dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.repetition_number              = 10; // should derived from MIB

		dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.number_of_subframes_for_resource_assignment     = 8;
		
		SCHED_info->TX_req->tx_request_body.tx_pdu_list[dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.pdu_index].segments[0].segment_data = SIB1_pdu;
		LOG_D(MAC,"[hypersfn:%2d][frame:%2d][subframe:%2d]NB-IoT fill SIB1\n",hypersfn,frame,subframe);
	}else if(schedule_result_list_DL == NULL){
		DL_empty = 1;
		LOG_D(MAC,"no remaining node of DL scheduling result\n");
	}else{
		//	here shouldn't be run into, to prevent DL scheduling result node is less than curent time
		if(schedule_result_list_DL->output_subframe < current_time)
		{
			while(schedule_result_list_DL->output_subframe < current_time)
			{
				//LOG_D(MAC,"This error if there is DL scheduling result node before the current time\n");
				tmp = schedule_result_list_DL;
				schedule_result_list_DL = schedule_result_list_DL->next;
				free(tmp);

				if(schedule_result_list_DL == NULL){
					return -1;
				}
			}

		}
		else if (schedule_result_list_DL->output_subframe == current_time) // output dci or data by using nfapi format
		{
			switch(schedule_result_list_DL->channel)
			{
				case NPDCCH:

					if(schedule_result_list_DL->direction == DL) // DCI for Downlink
					{
						LOG_D(MAC,"[hypersfn:%2d][frame:%2d][subframe:%2d]NB-IoT fill DL_DCI\n",hypersfn,frame,subframe);

						dl_config_pdu = SCHED_info->DL_req->dl_config_request_body.dl_config_pdu_list;
						SCHED_info->DL_req->dl_config_request_body.number_dci = 1;
                        SCHED_info->DL_req->dl_config_request_body.number_pdu = 1;
						DCI_pdu = schedule_result_list_DL->DCI_pdu;
						// not consider the case transmitting 2 DCIs for the moment also not consider N2 now
						dl_config_pdu->pdu_type                                                          = NFAPI_DL_CONFIG_NPDCCH_PDU_TYPE;
						dl_config_pdu->pdu_size                                                          = 2+sizeof(nfapi_dl_config_npdcch_pdu_rel13_t);
						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.length				                 = (schedule_result_list_DL->sdu_length)*8;
						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.pdu_index                             = 1;
						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.ncce_index                            = 0;
						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.aggregation_level     				 = 1;
						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti_type                             = schedule_result_list_DL->rnti_type; // 3 = UE-specific RNTI TODO: add RNTI type in scheduling result
						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti                                  = schedule_result_list_DL->rnti;
						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.dci_format                            = 0; // N1
						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.scheduling_delay                      = ((DCIFormatN1_t *)DCI_pdu)->Scheddly;
						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.resource_assignment                   = ((DCIFormatN1_t *)DCI_pdu)->ResAssign;
						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.repetition_number                     = ((DCIFormatN1_t *)DCI_pdu)->RepNum;
						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.mcs                                   = ((DCIFormatN1_t *)DCI_pdu)->mcs;
						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.new_data_indicator                    = ((DCIFormatN1_t *)DCI_pdu)->ndi;
						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.harq_ack_resource                     = ((DCIFormatN1_t *)DCI_pdu)->HARQackRes;
						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.npdcch_order_indication               = ((DCIFormatN1_t *)DCI_pdu)->orderIndicator;
						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.dci_subframe_repetition_number        = ((DCIFormatN1_t *)DCI_pdu)->DCIRep;
						LOG_D(MAC,"[hypersfn:%2d][frame:%2d][subframe:%2d]NB-IoT fill DL DCI, res:%d, rep:%d\n",hypersfn,frame,subframe,dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.resource_assignment,((DCIFormatN1_t *)DCI_pdu)->RepNum);

					}else if(schedule_result_list_DL->direction == UL) // DCI for uplink
					{
						LOG_D(MAC,"[hypersfn:%2d][frame:%2d][subframe:%2d]NB-IoT fill UL_DCI\n",hypersfn,frame,subframe);
						hi_dci0_pdu = SCHED_info->HI_DCI0_req->hi_dci0_request_body.hi_dci0_pdu_list;
						DCI_pdu = schedule_result_list_DL-> DCI_pdu;
						SCHED_info-> HI_DCI0_req->hi_dci0_request_body.number_of_dci =1;
						hi_dci0_pdu->pdu_type                                                            = NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE;
						hi_dci0_pdu->pdu_size                                                            = 2 + sizeof(nfapi_hi_dci0_npdcch_dci_pdu_rel13_t);
						hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.ncce_index                      = 0;
						hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.aggregation_level               = 1;
						hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.rnti                            = schedule_result_list_DL->rnti;
						hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.subcarrier_indication           = ((DCIFormatN0_t *)DCI_pdu)->scind;
						hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.resource_assignment             = ((DCIFormatN0_t *)DCI_pdu)->ResAssign;
						hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.scheduling_delay                = ((DCIFormatN0_t *)DCI_pdu)->Scheddly;
						hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.mcs                             = ((DCIFormatN0_t *)DCI_pdu)->mcs;
						hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.redudancy_version               = ((DCIFormatN0_t *)DCI_pdu)->rv;
						hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.repetition_number               = ((DCIFormatN0_t *)DCI_pdu)->RepNum;
						hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.new_data_indicator              = ((DCIFormatN0_t *)DCI_pdu)->ndi;
						hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.dci_subframe_repetition_number  = ((DCIFormatN0_t *)DCI_pdu)->DCIRep;
					}
					break;
				case NPDSCH: // Downlink Data
						LOG_D(MAC,"[hypersfn:%2d][frame:%2d][subframe:%2d]NB-IoT fill DL Data\n",hypersfn,frame,subframe);
						dl_config_pdu = SCHED_info->DL_req->dl_config_request_body.dl_config_pdu_list;
					    DCI_pdu = schedule_result_list_DL-> DCI_pdu;
                        SCHED_info->DL_req->dl_config_request_body.number_pdu = 1;
						dl_config_pdu->pdu_type                                           = NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE;
						dl_config_pdu->pdu_size                                           = 2+sizeof(nfapi_dl_config_ndlsch_pdu_rel13_t);
						dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.length                 = schedule_result_list_DL->sdu_length;
						dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.pdu_index			  = 1;
						dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.rnti_type              = 1;
						dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.rnti                   = schedule_result_list_DL->rnti; // C-RNTI
						dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.resource_assignment    = ((DCIFormatN1_t *)DCI_pdu)->ResAssign;
						dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.repetition_number      = ((DCIFormatN1_t *)DCI_pdu)->RepNum;
						dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.modulation             = 2;
						dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.number_of_subframes_for_resource_assignment = get_num_sf(dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.resource_assignment);
						SCHED_info->TX_req->tx_request_body.tx_pdu_list[dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.pdu_index].segments[0].segment_data = schedule_result_list_DL->DLSCH_pdu;
						if(schedule_result_list_DL->rnti==SI_RNTI)
						{
							// the table for SIB information is different from the table for normal uplink data
							dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.number_of_subframes_for_resource_assignment =((DCIFormatN1_t *)DCI_pdu)->ResAssign;
							dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.length                 = schedule_result_list_DL->sdu_length;
							LOG_D(MAC,"[hypersfn:%2d][frame:%2d][subframe:%2d]NB-IoT fill SIBs\n",hypersfn,frame,subframe);

						}else
							LOG_D(MAC,"[hypersfn:%2d][frame:%2d][subframe:%2d]NB-IoT fill DL Data, length = %d number of sf for a data = %d\n",hypersfn,frame,subframe,dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.length,dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.number_of_subframes_for_resource_assignment);
					break;
				default:
					break;
			}

			if(schedule_result_list_DL->DCI_release == 1)
				free(schedule_result_list_DL->DCI_pdu);
			
            tmp = schedule_result_list_DL;
			schedule_result_list_DL = schedule_result_list_DL->next;
			
		}
	}
	
	//	process uplink data transmission(s), might be multiple UL_REQ in one subframe (e.g. 1ms)
	if(schedule_result_list_UL==NULL)
	{
		UL_empty = 1;
		LOG_D(MAC,"no remaining node of UL scheduling result\n");
	}else
	{
		//	here shouldn't be run into
		if(schedule_result_list_UL->output_subframe < current_time)
		{
			while(schedule_result_list_UL->output_subframe < current_time)
			{
				//LOG_D(MAC,"This error if there is UL scheduling result node before the current time\n");
				tmp = schedule_result_list_UL;
				schedule_result_list_UL = schedule_result_list_UL->next;
				free(tmp);
				return -1;
			}
			//LOG_D(MAC,"return\n");
			//return -1;
		}
		else if(schedule_result_list_UL->output_subframe == current_time)
		{
			//SCHED_info->UL_req = (nfapi_ul_config_request_t *)malloc(sizeof(nfapi_ul_config_request_t));
			//SCHED_info->UL_req->ul_config_request_body.number_of_pdus = 0;
			SCHED_info->UL_req->ul_config_request_body.ul_config_pdu_list = (nfapi_ul_config_request_pdu_t *)malloc(5 * sizeof(nfapi_ul_config_request_pdu_t));
			ul_config_pdu = SCHED_info->UL_req->ul_config_request_body.ul_config_pdu_list;
		}	
		while(schedule_result_list_UL->output_subframe == current_time)
		{
			if(schedule_result_list_UL->channel == NPUSCH)  // condition should be added to switch between HI_DCI0 and Msg3
			{
				//LOG_D(MAC,"first UL \n");
				LOG_D(MAC,"[hypersfn:%2d][frame:%2d][subframe:%2d]NB-IoT fill UL config\n",hypersfn,frame,subframe);
				//SCHED_info->UL_req = (nfapi_ul_config_request_t *)malloc(sizeof(nfapi_ul_config_request_t));
				//SCHED_info->UL_req->ul_config_request_body.number_of_pdus = 0;
				//SCHED_info->UL_req->ul_config_request_body.ul_config_pdu_list = (nfapi_ul_config_request_pdu_t *)malloc(5 * sizeof(nfapi_ul_config_request_pdu_t));
			
				SCHED_info->UL_req->ul_config_request_body.number_of_pdus ++;
				//SCHED_info->UL_req.sfn_sf = ;
				(ul_config_pdu + i) ->pdu_type                                            = NFAPI_UL_CONFIG_NULSCH_PDU_TYPE;
				(ul_config_pdu + i) ->pdu_size                                            = 2 + sizeof(nfapi_ul_config_nulsch_pdu_rel13_t);

				if(schedule_result_list_UL->npusch_format == 0){
					DCI_pdu = schedule_result_list_UL->DCI_pdu;
					// bug here
					(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.nulsch_format           = 0;

					//contidition should be added to select either the UL_TBS_Table or t UL_TBS_table_msg3
					// ******* sc_spacing issues to be fixed next *******////
					uint8_t sc_spacing = 1;  // 1 for 15 KHz , 0 for 3.75 KHz  // TODO, get this value from scheduler
					//(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.handle           = sc_spacing; 
					//(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.size                    = UL_TBS_Table[((DCIFormatN0_t *)DCI_pdu)->mcs][((DCIFormatN0_t *)DCI_pdu)->ResAssign];
					//(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.size                    = UL_TBS_Table[get_UL_I_TBS_from_MCS_NB_IoT(((DCIFormatN0_t *)DCI_pdu)->mcs, get_N_RU(((DCIFormatN0_t *)DCI_pdu)->ResAssign), 0)][((DCIFormatN0_t *)DCI_pdu)->ResAssign];
					// get_UL_I_TBS_from_MCS_NB_IoT() to  be used to get the I_TBS for any NPUSCH format 
					
					if(schedule_result_list_UL->msg3_flag ==1)  
					{
					   (ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.size                    = UL_TBS_Table_msg3[get_UL_I_TBS_from_MCS_NB_IoT(((DCIFormatN0_t *)DCI_pdu)->mcs, test_signle_tone_UL_NB_IoT(sc_spacing,((DCIFormatN0_t *)DCI_pdu)->scind, 0), 1)]/8;   // for the case of MSG3 
					   LOG_I(MAC,"process msg3 at output handler, size = %d\n",(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.size);
					} else 
					{
					 	//(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.size                    = UL_TBS_Table[get_UL_I_TBS_from_MCS_NB_IoT(((DCIFormatN0_t *)DCI_pdu)->mcs, get_N_RU(((DCIFormatN0_t *)DCI_pdu)->ResAssign), 0)][((DCIFormatN0_t *)DCI_pdu)->ResAssign]/8;   // for the case of other NPUSH msgs
					    (ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.size                    = UL_TBS_Table[get_UL_I_TBS_from_MCS_NB_IoT(((DCIFormatN0_t *)DCI_pdu)->mcs,1,0)][((DCIFormatN0_t *)DCI_pdu)->ResAssign]/8;   // for the case of other NPUSH msgs
					    LOG_I(MAC,"Process uplink data at output handler, size = %d\n",(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.size);
					}
					//LOG_D(MAC,"test\n");
					(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.rnti                    = schedule_result_list_UL->rnti;  //TODO : check if it is the right rnti // get from msg2
					(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.subcarrier_indication   = ((DCIFormatN0_t *)DCI_pdu)->scind;
					(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.resource_assignment     = ((DCIFormatN0_t *)DCI_pdu)->ResAssign;  // this value is the I_RU ??
					(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.mcs                     = ((DCIFormatN0_t *)DCI_pdu)->mcs;
					(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.redudancy_version       = ((DCIFormatN0_t *)DCI_pdu)->rv;
					(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.repetition_number       = ((DCIFormatN0_t *)DCI_pdu)->RepNum;
					(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.new_data_indication     = ((DCIFormatN0_t *)DCI_pdu)->ndi;

				} else if(schedule_result_list_UL->npusch_format == 1){
					DCI_pdu = schedule_result_list_UL->DCI_pdu;
					(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.nulsch_format       = 1;

                    (ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.size                = 16;

					(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.rnti                    = schedule_result_list_UL->rnti;
					//(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.subcarrier_indication   = ((DCIFormatN0_t *)DCI_pdu)->scind;
					//(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.resource_assignment     = ((DCIFormatN0_t *)DCI_pdu)->ResAssign;
					//(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.repetition_number       = ((DCIFormatN0_t *)DCI_pdu)->RepNum;

					(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.ue_information.ue_information_rel13.total_number_of_repetitions = schedule_result_list_UL->R_harq;
					//for ACK /NACK
					(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.nb_harq_information.nb_harq_information_rel13_fdd.harq_ack_resource = ((DCIFormatN1_t *)DCI_pdu)->HARQackRes;
				}
				
                if(schedule_result_list_UL->DCI_release == 1){
                    free(schedule_result_list_UL->DCI_pdu);
                }
                
                tmp = schedule_result_list_UL;
				schedule_result_list_UL = schedule_result_list_UL->next;
				
				free(tmp);

				i++;

				if(schedule_result_list_UL == NULL)
					break;
			}else{
				//	there should only be NPUSCH, no exception
				LOG_D(MAC,"error\n");
			}
		}
	}

	LOG_D(MAC,"[hypersfn:%2d][frame:%2d][subframe:%2d]filling the schedule response successfully\n",hypersfn,frame,subframe);

	return 0;
}