/**
 * @file schedular.c
 *
 * @brief This file contains APIs for scheduler.
 *
 * The functions provided in the file has scheduler control thread that monitors and controls Scheduled events, Compares system time with Event time and triggers the event when both the time matches.

 * * @copyright Copyright 2023 Antaris, Inc.
 *
 * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
 *
 * 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.
 */
/*********************************************************************/

#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "exo_common.h"
#include "exo_osal.h"
#include "exo_io_al_sos_timer.h"
#include "obc_icd.h"
#include "schedular.h"
#include "eps_ctrlr.h"
#include "nvm.h"
#include "logger.h"
#include "obc_tc_tm.h"
#include "file_integrity_check.h"
#include "exo_tctm_ipc.h"
os_timer_handle_ptr   		conops_sch_sat_init_tmr,conops_sch_evnt_tmr;

conops_sch_lut_info_rcd_s 	*conops_sch_lut_info_rcd;
conops_sch_lut_info_s 	    conops_sch_lut_info[SCH_GRP_ID_MAX_CNT];
conops_sch_evnt_s 			*conops_sch_crnt_evnt;
sys_time_date_s 			sch_time_date;
uint16_t					conops_sch_lut_info_segmnt_copy_prog[SCH_GRP_ID_MAX_CNT];
uint8_t 					conops_sch_lut_grp_crnt_num = CONOPS_SCH_LUT_STS_IDLE;
uint8_t 					conops_sch_evnt_pending_sts = CONOPS_SCH_LUT_STS_IDLE;
uint8_t 					*nvm_evnt_buff = NULL;
uint8_t 					conops_sch_obc_deinit=0;
uint8_t check_first_trig;
extern uint8_t reset_cause;


/**
 * @brief This API executes the given scheduler LUT event - It sends IPC message to the corresponding module with event information to be
 * executed
 *
 * @param[in]  _sch_evnt : structure pointer gives value of event to be executed
 *
 */
void conops_sch_trig_event(conops_sch_evnt_s *_sch_evnt);


/**
 * @brief cononps scheduler thread that handles state machine which manages LUT reception and  execution of the events
 *
 * Execution of the events include:
 * 1.Start
 * 2.Pause
 * 3.Stop
 * 4.Erase
 */

void *conops_sch_proc();



/**
 * @brief This API is used to send IPC message with scheduler thread
 */

conops_sch_sts_e conops_sch_send_ipc_msg_pld(uint8_t dst_id, uint8_t pld_info, uint16_t msg_id, uint8_t *pld, uint8_t pld_size)
{
	os_itc_msg_handle_t sch_send_ipc;
	sch_send_ipc.src_entity = ORBIT_CONOPS_SCHEDULER;

	sch_send_ipc.Msg_id 	  = msg_id;
	sch_send_ipc.pld_info 	  = pld_info;
	sch_send_ipc.Msg_len	  = pld_size;

	if(pld_size)
	{
		sch_send_ipc.pld.pld_ptr = os_malloc(pld_size);
		os_memcpy(sch_send_ipc.pld.pld_ptr,pld,pld_size);
	}
	else
		sch_send_ipc.pld.pld_ptr = NULL;

	if(os_itc_msg_send(&sch_send_ipc,dst_id,os_send_itc_wait) != ral_success)
	{
#ifdef SCH_PRINT_EN
		DEBUG_CPRINT(("OBC APP ITC Message send fail\n"));
#endif
		log_id(LOG_ERROR,LOG_SCHEDULER,OBC_APP_ITC_MESSAGE_SEND_FAIL);
		os_free(sch_send_ipc.pld.pld_ptr);
		sch_send_ipc.pld.pld_ptr = NULL;
		return CONOPS_SCH_ERR;
	}
	else
		return CONOPS_SCH_SUCSS;
}

/*
 *@brief This API trigger timer to start the event by comparing system time and event time. 
 *
 */

conops_sch_sts_e conops_sch_trig_timer(conops_sch_evnt_info_s *_conops_sch_evnt_info)
{
	uint32_t sys_time_epoch=0;
	uint32_t event_time_epoch=0;
	uint32_t  conops_sch_secs_cnt=0;
	conops_sch_sts_e conops_sch_sts  = CONOPS_SCH_SUCSS;

	sys_time_epoch=get_crnt_time_date_in_epoch();
	os_memcpy(&event_time_epoch,&_conops_sch_evnt_info->epoch,sizeof(uint32_t));
	//event_time_epoch=_conops_sch_evnt_info->epoch;
#ifdef SCH_PRINT_EN
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat"
	DEBUG_CPRINT(("D:%d ",_conops_sch_evnt_info->dest_id));
	DEBUG_CPRINT(("E:%d ",_conops_sch_evnt_info->id));
	DEBUG_CPRINT(("ST:%d ", sys_time_epoch));
	DEBUG_CPRINT(("ET: %d ", event_time_epoch));
#pragma GCC diagnostic pop
#endif

	log_id_with_four_arg(LOG_INFO_L2,LOG_SCHEDULER,D_u8_E_u8__ST__u32__ET__u32_,_conops_sch_evnt_info->dest_id,_conops_sch_evnt_info->id,sys_time_epoch,event_time_epoch);

	if(event_time_epoch>=sys_time_epoch)
	{

		conops_sch_secs_cnt=(event_time_epoch)-(sys_time_epoch);

#ifdef SCH_PRINT_EN
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat"
		DEBUG_CPRINT(("Time Diff:%d\n",conops_sch_secs_cnt));
#pragma GCC diagnostic pop
#endif
		log_id_with_one_arg(LOG_INFO_L3,LOG_SCHEDULER,TIME_DIFF__u32_,conops_sch_secs_cnt);

		if(conops_sch_secs_cnt>TWODAYS_IN_SECS)
		{
			conops_sch_sts=CONOPS_SCH_ERR;
			log_id(LOG_ERROR,LOG_SCHEDULER,DATE_ERROR);
			DEBUG_CPRINT(("-DATE_ERR]\n"));
		}
		else
		{
			conops_sch_crnt_evnt = os_malloc(sizeof(conops_sch_evnt_s));
			os_memcpy(&(conops_sch_crnt_evnt->arg1),&(_conops_sch_evnt_info->arg1),4);
			os_memcpy(&(conops_sch_crnt_evnt->arg2),&(_conops_sch_evnt_info->arg2),4);
			os_memcpy(&(conops_sch_crnt_evnt->id),&(_conops_sch_evnt_info->id),2);
			os_memcpy(&(conops_sch_crnt_evnt->dest_id),&(_conops_sch_evnt_info->dest_id),1);
			os_memcpy(&(conops_sch_crnt_evnt->src_id),&(_conops_sch_evnt_info->src_id),1);

			if(conops_sch_secs_cnt>0)
			{
				os_timer_start(conops_sch_evnt_tmr,(conops_sch_secs_cnt*1000));
			}
			else
				conops_sch_send_ipc_msg_pld(ORBIT_CONOPS_SCHEDULER,0,CONOPS_SCH_EVNT_EXEC,NULL,0);

		}
	}
	else
	{
		conops_sch_sts=CONOPS_SCH_ERR;
		DEBUG_CPRINT(("-TIME_ERR\n"));
		log_id(LOG_ERROR,LOG_SCHEDULER,TIME_ERROR);
	}

	return conops_sch_sts;

}


/**
 * @brief This API checks next event present in the group based on total and current group segment
 * 		  and updates the completed group segment information
 *
 * @return conops_sch_sts_e : success/ failure status of conversion
 * @retval  zero - success , greater than zero failure
 *
 */

conops_sch_sts_e conops_sch_check_next_evnt(conops_sch_lut_info_s *_conops_sch_lut_info,uint8_t _grp_id)
{
	conops_sch_sts_e conops_sch_sts = CONOPS_SCH_ERR;
	if(_conops_sch_lut_info->crnt_evnt_cnt >=  _conops_sch_lut_info->seg_map[_conops_sch_lut_info->crnt_seg_cnt].evnt_info_cnt)
	{

#ifdef SCH_PRINT_EN
		DEBUG_CPRINT(("SEG_EXEC_CMPLT[%u][%u]\n",_grp_id,_conops_sch_lut_info->crnt_seg_cnt));
#endif
		log_id_with_two_arg(LOG_INFO_L1 ,LOG_SCHEDULER,SEG_EXEC_CMPLT_u8__u8_,_grp_id,_conops_sch_lut_info->crnt_seg_cnt);

		_conops_sch_lut_info->crnt_evnt_cnt = 0;

		if((check_first_trig != SCH_OBC_SYNC_EVNT_STRT) || (_grp_id !=1))
		{
			_conops_sch_lut_info->cmpl_seg_bin |= ((uint64_t)1 << _conops_sch_lut_info->crnt_seg_cnt);

			if(_conops_sch_lut_info->seg_map[_conops_sch_lut_info->crnt_seg_cnt].evnt_buff != NULL)
			{
				os_free(_conops_sch_lut_info->seg_map[_conops_sch_lut_info->crnt_seg_cnt].evnt_buff);
				_conops_sch_lut_info->seg_map[_conops_sch_lut_info->crnt_seg_cnt].evnt_buff = NULL;

			}
		}
		do
		{
			_conops_sch_lut_info->crnt_seg_cnt++;
			if(_conops_sch_lut_info->crnt_seg_cnt >= _conops_sch_lut_info->totl_seg)
			{      				// group event complete
				if((check_first_trig != SCH_OBC_SYNC_EVNT_STRT) || (_grp_id !=1))
				{
					os_free(_conops_sch_lut_info->seg_map);
					_conops_sch_lut_info->seg_map = NULL;
					_conops_sch_lut_info->grp_sts = SCH_LUT_EXEC_CMPLT;
				}

				conops_sch_send_ipc_msg_pld(ORBIT_CONOPS_SCHEDULER,0,CONOPS_SCH_LUT_CMPLT,&_grp_id,1);
				conops_sch_sts = CONOPS_SCH_SUCSS;
				return 	conops_sch_sts;
			}
		}
		while((_conops_sch_lut_info->rcd_seg_bin & ((uint64_t)1 << _conops_sch_lut_info->crnt_seg_cnt))==0);

		nvm_parameter_write(NVM_DATA,CONOPS_SCH_LUT_INFO_0+_grp_id,(uint8_t*)&conops_sch_lut_info[_grp_id]);
	}

#ifdef SCH_PRINT_EN
	DEBUG_CPRINT(("\nSCH_TRIG [No:G%uS%uE%u]",_grp_id, _conops_sch_lut_info->crnt_seg_cnt,_conops_sch_lut_info->crnt_evnt_cnt));
#endif

	log_id_with_three_arg(LOG_INFO_L1,LOG_SCHEDULER,TRIG_No__G_u8_S_u8_E_u8_,_grp_id,_conops_sch_lut_info->crnt_seg_cnt,_conops_sch_lut_info->crnt_evnt_cnt);

	if(conops_sch_trig_timer(&_conops_sch_lut_info->seg_map[_conops_sch_lut_info->crnt_seg_cnt].evnt_buff[_conops_sch_lut_info->crnt_evnt_cnt]) != CONOPS_SCH_SUCSS)
	{
		conops_sch_send_ipc_msg_pld(ORBIT_CONOPS_SCHEDULER,0,CONOPS_SCH_EVNT_NXT_TMR,NULL,0);
		conops_sch_sts =  	CONOPS_SCH_ERR;
	}
	_conops_sch_lut_info->crnt_evnt_cnt++;

	return conops_sch_sts;
}


/**
 * @brief copy events received from ground station to scheduler local LUT buffer
 *
 */

uint16_t conops_sch_lut_info_segmnt_copy(uint8_t *_data)
{
	uint16_t evnt_info_cnt_byte_tmp =  sizeof(conops_sch_evnt_info_s);
	conops_sch_evnt_info_s *evnt_buff1=NULL;

	if((_data[0] < SCH_GRP_ID_MAX_CNT) /*  &&  (_data[2] == 0)*/)
	{

		conops_sch_lut_info_rcd                         = os_malloc(sizeof(conops_sch_lut_info_rcd_s));
		conops_sch_lut_info_rcd->grp_id                 = _data[0];
		conops_sch_lut_info_rcd->totl_cnt               = _data[1];
		conops_sch_lut_info_rcd->crnt_num               = _data[2];
		conops_sch_lut_info_rcd->trig_type              = _data[3];
		conops_sch_lut_info_rcd->evnt_info_cnt          = _data[4];
		evnt_info_cnt_byte_tmp                          = _data[4] * evnt_info_cnt_byte_tmp;//sizeof(conops_sch_evnt_info_s);

		evnt_buff1 = os_malloc_eram(evnt_info_cnt_byte_tmp);
		conops_sch_lut_info_rcd->evnt_buff              = evnt_buff1;

		if(conops_sch_lut_info_rcd->evnt_buff != NULL)
		{
			os_memcpy((void *)conops_sch_lut_info_rcd->evnt_buff,(void *)&_data[5],evnt_info_cnt_byte_tmp);

			conops_sch_send_ipc_msg_pld(ORBIT_CONOPS_SCHEDULER,0, CONOPS_SCH_LUT_COPY,(uint8_t *)conops_sch_lut_info_rcd,sizeof(conops_sch_lut_info_rcd_s));

			evnt_info_cnt_byte_tmp = conops_sch_lut_info_rcd->grp_id;
			evnt_info_cnt_byte_tmp = (evnt_info_cnt_byte_tmp<<8) | (conops_sch_lut_info_rcd->crnt_num);
		}
		else
			evnt_info_cnt_byte_tmp = 0;

		os_free(conops_sch_lut_info_rcd);
		conops_sch_lut_info_rcd = NULL;
	}
	else
		evnt_info_cnt_byte_tmp = 0xFFFF;

	return evnt_info_cnt_byte_tmp;
}


/**
 * @brief This API send IPC message for  LUT save, start, pause, stop and erase to conops_sch_proc based on the input command from ground station 
 *
 */

conops_sch_sts_e conops_sch_lut_trig_req(uint8_t *_data)
{
	uint8_t sts = 0, group_sts;

	if( _data[0] < SCH_GRP_ID_MAX_CNT)
	{
		sts = CONOPS_SCH_ERR;
		group_sts = conops_sch_lut_info[_data[0]].grp_sts;
		//data0 -> grp_id data1 = condition
		switch(_data[1])
		{
		case CONOPS_SCH_LUT_SAVE:
			if(group_sts != SCH_LUT_IDLE)
			{
				_data[1] = CONOPS_SCH_LUT_SAVE;
				sts = CONOPS_SCH_SUCSS;
			}
			break;
		case CONOPS_SCH_LUT_STRT:
			if(group_sts != SCH_LUT_IDLE)
			{
				_data[1] = CONOPS_SCH_LUT_SAVE_STRT;
				sts = CONOPS_SCH_SUCSS;
			}
			break;
		case CONOPS_SCH_LUT_PAUSE:
			if(group_sts  == SCH_LUT_EXEC_PROG)
				sts = CONOPS_SCH_SUCSS;
			break;
		case CONOPS_SCH_LUT_STOP:
			if(group_sts  == SCH_LUT_EXEC_PROG)
				sts = CONOPS_SCH_SUCSS;
			break;
		case CONOPS_SCH_LUT_ERASE:
		{
			if(group_sts  != SCH_LUT_EXEC_PROG)
				sts = CONOPS_SCH_SUCSS;
		}
		break;
		default:
			sts = CONOPS_PARAM_ERR;
		}
		if(sts == CONOPS_SCH_SUCSS)
		{
			conops_sch_send_ipc_msg_pld(ORBIT_CONOPS_SCHEDULER,0,_data[1],&_data[0],1);

#ifdef SCH_PRINT_EN
			DEBUG_CPRINT(("\nTRIG_REQ %u-%u\n",_data[0],_data[1]));
#endif
			log_id_with_two_arg(LOG_INFO_L1,LOG_SCHEDULER,TRIG_REQ__u8__u8_,_data[0],_data[1]);
		}
		else
		{
#ifdef SCH_PRINT_EN
			DEBUG_CPRINT(("\nTRIG_REQ %u-%u - ERROR\n",_data[0],_data[1])); // update as error
#endif
			log_id_with_two_arg(LOG_ERROR,LOG_SCHEDULER,TRIG_REQ_ERROR__u8__u8_,_data[0],_data[1]);
		}
	}
	return sts;
}

/**
 * @brief This API gives lut status information to ground station
 *
 */
void conops_sch_lut_info_tm_pack(uint8_t cmd, uint8_t **tm_frame_data, uint16_t *tm_frame_len)
{
		uint8_t cnt=0,frame_len;
		uint8_t *tm_frame = NULL;
		frame_len = sizeof(conops_sch_lut_info_s);

		 if(cmd < SCH_GRP_ID_MAX_CNT)
		 {
			 tm_frame = os_malloc(frame_len +1);
			 os_memcpy(&tm_frame[1], &conops_sch_lut_info[cmd],frame_len);
		 }
		 else
		 {
			 tm_frame = os_malloc((SCH_GRP_ID_MAX_CNT * frame_len) +1);

			 for(cnt=0; cnt<SCH_GRP_ID_MAX_CNT; cnt++)
			 {
				 os_memcpy(&tm_frame[1+(cnt*frame_len)], &conops_sch_lut_info[cnt], frame_len);
			 }

			 frame_len = SCH_GRP_ID_MAX_CNT *frame_len;
		 }
		 tm_frame[0] =  cmd;
		 *tm_frame_data = tm_frame;
		 *tm_frame_len = (uint16_t)frame_len;
}


/**
 * @brief This API frees the memory of the LUT based on the group ID given 
 *
 *
 */

void conops_sch_lut_free(uint8_t _grp_id)
{
	uint8_t i = 0;

#ifdef SCH_PRINT_EN
	DEBUG_CPRINT(("SCH_CLR_LUT-%d\n",_grp_id));
#endif
	log_id_with_one_arg(LOG_INFO_L2,LOG_SCHEDULER,CLR_LUT__u8_,_grp_id);

	if(conops_sch_lut_info[_grp_id].rcd_seg_bin != conops_sch_lut_info[_grp_id].cmpl_seg_bin)
	{
		//clearing all individual buffer segment
		while(i<conops_sch_lut_info[_grp_id].totl_seg)
		{
			if(conops_sch_lut_info[_grp_id].seg_map[i].evnt_buff != NULL)
			{
				os_free((void *)conops_sch_lut_info[_grp_id].seg_map[i].evnt_buff);
				conops_sch_lut_info[_grp_id].seg_map[i].evnt_buff = NULL;
			}
			i++;
		}
	}

	//clearing all overall buffer segment
	if(conops_sch_lut_info[_grp_id].seg_map != NULL)
	{
		os_free(conops_sch_lut_info[_grp_id].seg_map);
		conops_sch_lut_info[_grp_id].seg_map	=	NULL;
	}

	conops_sch_lut_info[_grp_id].totl_seg	 	= 0;
	conops_sch_lut_info[_grp_id].rcd_seg_bin  	= 0;
	conops_sch_lut_info[_grp_id].crnt_seg_cnt 	= 0;
	conops_sch_lut_info[_grp_id].crnt_evnt_cnt 	= 0;
	conops_sch_lut_info[_grp_id].cmpl_seg_bin  	= 0;
	conops_sch_lut_info[_grp_id].grp_sts  		= SCH_LUT_IDLE;

	conops_sch_evnt_pending_sts &= ~((uint8_t)0x01 << _grp_id);
	nvm_parameter_write(NVM_DATA,CONOPS_SCH_EVNT_PENDING_STS,(uint8_t*)&conops_sch_evnt_pending_sts);
	nvm_parameter_write(NVM_DATA,CONOPS_SCH_LUT_INFO_0+_grp_id,(uint8_t*)&conops_sch_lut_info[_grp_id]);
}


/**
 * @brief This API creates memory and copies the events into received structure memory 
 * Depending on the group status,this API copies the events and LUT is ready for execution
 */

conops_sch_sts_e conops_sch_lut_info_copy(conops_sch_lut_info_rcd_s *_conops_sch_lut_info)
{
	uint8_t temp_cnt=0;
	uint8_t lut_grp_id = _conops_sch_lut_info->grp_id;
	uint8_t lut_seg_num = _conops_sch_lut_info->crnt_num;

#ifdef SCH_PRINT_EN
	DEBUG_CPRINT(("SCH_LUT_RX G%uS%u",lut_grp_id,lut_seg_num));
#endif
	log_id_with_two_arg(LOG_INFO_L1,LOG_SCHEDULER,LUT_RX_G_u8_S_u8_,lut_grp_id,lut_seg_num);
	switch(conops_sch_lut_info[lut_grp_id].grp_sts)
	{
	case SCH_LUT_IDLE:  // clearing available memories
	{
		conops_sch_lut_info[lut_grp_id].totl_seg	 	= _conops_sch_lut_info->totl_cnt;
		conops_sch_lut_info[lut_grp_id].seg_map 		= os_malloc(sizeof(conops_sch_lut_seg_map_s)*_conops_sch_lut_info->totl_cnt);
		for(temp_cnt=0;temp_cnt<_conops_sch_lut_info->totl_cnt;temp_cnt++) //clearing malloc values
		{
			conops_sch_lut_info[lut_grp_id].totl_seg_bin 										   |=  ((uint32_t)1<<temp_cnt);
			conops_sch_lut_info[lut_grp_id].seg_map[lut_seg_num].trig_type		= 0;
			conops_sch_lut_info[lut_grp_id].seg_map[lut_seg_num].evnt_info_cnt	= 0;
			conops_sch_lut_info[lut_grp_id].seg_map[temp_cnt].evnt_buff = NULL;
		}
		conops_sch_lut_info[lut_grp_id].grp_sts  		= SCH_LUT_RX_PROG;
#ifdef SCH_PRINT_EN
		DEBUG_CPRINT((" NEW_LUT-TotSeg%u",conops_sch_lut_info[lut_grp_id].totl_seg));
#endif
		log_id_with_one_arg(LOG_INFO_L1,LOG_SCHEDULER,NEW_LUT_TOTSEG_u8_,conops_sch_lut_info[lut_grp_id].totl_seg);
	}

	case SCH_LUT_EXEC_PROG:
	case SCH_LUT_RDY:
	case SCH_LUT_RX_PROG:
	{
		if(lut_seg_num < conops_sch_lut_info[lut_grp_id].totl_seg)
		{
			if(conops_sch_lut_info[lut_grp_id].grp_sts == SCH_LUT_EXEC_PROG)
			{	// need to stop current trigger and update the event
				if(conops_sch_lut_info[lut_grp_id].crnt_seg_cnt  == lut_seg_num)
					conops_sch_lut_info_segmnt_copy_prog[lut_grp_id] = 1;
			}

			if(conops_sch_lut_info[lut_grp_id].seg_map[lut_seg_num].evnt_buff != NULL)
			{
				os_free(conops_sch_lut_info[lut_grp_id].seg_map[lut_seg_num].evnt_buff);
				conops_sch_lut_info[lut_grp_id].seg_map[lut_seg_num].evnt_buff = NULL;

			}

			conops_sch_lut_info[lut_grp_id].seg_map[lut_seg_num].trig_type   	=_conops_sch_lut_info->trig_type;
			conops_sch_lut_info[lut_grp_id].seg_map[lut_seg_num].evnt_info_cnt  =_conops_sch_lut_info->evnt_info_cnt;
			os_memcpy(&conops_sch_lut_info[lut_grp_id].seg_map[lut_seg_num].evnt_buff,&_conops_sch_lut_info->evnt_buff,sizeof(_conops_sch_lut_info->evnt_buff));
			conops_sch_lut_info[lut_grp_id].rcd_seg_bin 					   |=  ((uint64_t)1<<lut_seg_num);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat"
			DEBUG_CPRINT((" bin-0x%lx",conops_sch_lut_info[lut_grp_id].rcd_seg_bin));
#pragma GCC diagnostic pop
			log_id_with_one_arg(LOG_INFO_L1,LOG_SCHEDULER,BIN__hex_,conops_sch_lut_info[lut_grp_id].rcd_seg_bin);

			if(conops_sch_lut_info[lut_grp_id].grp_sts == SCH_LUT_RX_PROG)
			{
				if(conops_sch_lut_info[lut_grp_id].totl_seg_bin == conops_sch_lut_info[lut_grp_id].rcd_seg_bin)
				{
					conops_sch_lut_info[lut_grp_id].grp_sts  =SCH_LUT_RDY;
					conops_sch_lut_info[lut_grp_id].crnt_seg_cnt = 0;
					conops_sch_lut_info[lut_grp_id].crnt_evnt_cnt = 0;

#ifdef SCH_PRINT_EN
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat"
					DEBUG_CPRINT(("\nSCH_LUT_RDY-0x%lx",conops_sch_lut_info[lut_grp_id].rcd_seg_bin));
#pragma GCC diagnostic pop
#endif
					log_id_with_one_arg(LOG_INFO_L1,LOG_SCHEDULER,LUT_RDY_hex_,conops_sch_lut_info[lut_grp_id].rcd_seg_bin);
				}
			}

			if(conops_sch_lut_info_segmnt_copy_prog[lut_grp_id])
			{
				conops_sch_lut_info[lut_grp_id].crnt_evnt_cnt 	 = 0;
				conops_sch_lut_info_segmnt_copy_prog[lut_grp_id] = 0;
				conops_sch_send_ipc_msg_pld(ORBIT_CONOPS_SCHEDULER,0,CONOPS_SCH_EVNT_NXT_TMR,NULL,0);
			}
		}
		else
		{
#ifdef SCH_PRINT_EN
			DEBUG_CPRINT(("LUT_SEG_CNT_ERR"));
#endif
			log_id(LOG_ERROR,LOG_SCHEDULER,LUT_SEG_CNT_ERR);

			if(_conops_sch_lut_info->evnt_buff != NULL)
			{
				os_free(_conops_sch_lut_info->evnt_buff);
				_conops_sch_lut_info->evnt_buff = NULL;
			}
			return CONOPS_SCH_ERR;
		}
	}
	}
#ifdef SCH_PRINT_EN
	DEBUG_CPRINT(("\n"));
#endif
	return CONOPS_SCH_SUCSS;
}


/**
 * @brief start scheduler event timer trigger for successive event
 *
 * @param[in] time: timer value in seconds
 *
 */

void conops_sch_timer_trig(uint32_t time)  //timer in seconds
{
	os_timer_start(conops_sch_evnt_tmr,(os_tick_time_t)time *1000);
}



/**
 * @brief Timer callback when scheduler timer expired
 *
 */

void conops_sch_evnt_cb()
{
	conops_sch_send_ipc_msg_pld(ORBIT_CONOPS_SCHEDULER,0,CONOPS_SCH_EVNT_EXEC,NULL,0);
}


/**
 * @brief Timer initialization for orbit complete event timer and payload ZES event timer
 */

void conops_sch_timer_init()
{
	os_timer_create(&conops_sch_evnt_tmr,"sch_evnt",ONESHOT,conops_sch_evnt_cb,NULL);
}


/**
 * @brief Timer de-initialization for orbit complete event timer and payload zes event timer
 */

void conops_sch_timer_deinit()
{
	os_timer_stop(conops_sch_evnt_tmr);
}


/**
 * @brief This API initialize the scheduler main FSM thread
 */

void conops_sch_init()
{
	os_thread_create(ORBIT_CONOPS_SCHEDULER,T_SCH_STACK_SIZE,P_ORBIT_CONOPS_SCHEDULER,"sch_proc", (app_entry_func_t)conops_sch_proc,NULL,NULL,NULL);
}


/**
 * @brief This API de-initialize the scheduler main FSM thread
 */

void conops_sch_deinit()
{
	conops_sch_timer_deinit();
	os_thread_delete(ORBIT_CONOPS_SCHEDULER);
}

/**
 * @brief This API copies received LUT data to NVM memory
 *
 */

void conops_sch_lut_info_copy_to_nvm(uint8_t lut_cnt)
{
	uint16_t evnt_offset_cnt,i=0,cpy_size=0,total_size=0;
	uint32_t evnt_buff_chk_sum = 0;

	if(lut_cnt < SCH_GRP_ID_MAX_CNT)
	{
		nvm_parameter_write(NVM_DATA,CONOPS_SCH_LUT_INFO_0+lut_cnt,(uint8_t*)&conops_sch_lut_info[lut_cnt]);

		for(i=0;i<conops_sch_lut_info[lut_cnt].totl_seg;i++)
		{
			evnt_offset_cnt = (i*EVNT_BFR_OFFSET);

			nvm_evnt_buff[evnt_offset_cnt] = conops_sch_lut_info[lut_cnt].seg_map[i].evnt_info_cnt;

			cpy_size = nvm_evnt_buff[evnt_offset_cnt]*sizeof(conops_sch_evnt_info_s);
			evnt_offset_cnt++;

			os_memcpy(&nvm_evnt_buff[evnt_offset_cnt],conops_sch_lut_info[lut_cnt].seg_map[i].evnt_buff,cpy_size);
			total_size +=cpy_size;

		}

		conops_sch_evnt_pending_sts |= (0x01 << lut_cnt);
		evnt_buff_chk_sum = calc_checksum_bulkdata(nvm_evnt_buff, LUT_SIZE - 4);
		os_memcpy(&nvm_evnt_buff[LUT_SIZE - 4], &evnt_buff_chk_sum, 4);

		nvm_parameter_write(NVM_DATA,CONOPS_SCH_EVNT_BUFF_0+lut_cnt,&nvm_evnt_buff[0]);
		nvm_parameter_write(NVM_DATA,CONOPS_SCH_EVNT_PENDING_STS,(uint8_t*)&conops_sch_evnt_pending_sts);
	}
}

/**
 * @brief This API copies data from NVM memory to LUT buffer 
 *
 */
void conops_sch_lut_info_copy_from_nvm()
{
	conops_sch_evnt_info_s *_evnt_buff = NULL;
	uint8_t seg_cnt=0,lut_cnt=0,sch_crnt_lut_cnt;
	uint16_t cpy_size,evnt_offset_cnt=0;
	conops_sch_evnt_pending_sts = CONOPS_SCH_LUT_STS_IDLE;
	uint32_t evnt_buff_chk_sum = 0, calc_check_sum = 0;

#ifdef	SCH_FIRST_TRIG_EN
	nvm_parameter_read(NVM_DATA,RSVD_BIT_21,&check_first_trig);
#endif

	nvm_parameter_read(NVM_DATA,CONOPS_SCH_CRNT_EVNT,&sch_crnt_lut_cnt);
	nvm_parameter_read(NVM_DATA,CONOPS_SCH_EVNT_PENDING_STS,(uint8_t*)&conops_sch_evnt_pending_sts);

	if((conops_sch_evnt_pending_sts != CONOPS_SCH_LUT_STS_IDLE)  && (conops_sch_evnt_pending_sts != 0))
	{
		while(lut_cnt < SCH_GRP_ID_MAX_CNT)
		{
			if(conops_sch_evnt_pending_sts & (0x01 << lut_cnt))
			{
				nvm_parameter_read(NVM_DATA,CONOPS_SCH_LUT_INFO_0+lut_cnt,(uint8_t*)&conops_sch_lut_info[lut_cnt]);

				if(conops_sch_lut_info[lut_cnt].grp_sts > SCH_LUT_EXEC_STOP)
				{
					conops_sch_lut_info[lut_cnt].seg_map = os_malloc(sizeof(conops_sch_lut_seg_map_s)*conops_sch_lut_info[lut_cnt].totl_seg);

					nvm_parameter_read(NVM_DATA,(CONOPS_SCH_EVNT_BUFF_0+lut_cnt),nvm_evnt_buff);

					os_memcpy(&evnt_buff_chk_sum, &nvm_evnt_buff[LUT_SIZE - 4], 4);
					calc_check_sum = calc_checksum_bulkdata(nvm_evnt_buff, LUT_SIZE - 4);

					if(evnt_buff_chk_sum == calc_check_sum)
					{
						for(seg_cnt=0;seg_cnt<conops_sch_lut_info[lut_cnt].totl_seg;seg_cnt++)
						{
							evnt_offset_cnt = (seg_cnt*EVNT_BFR_OFFSET);
							conops_sch_lut_info[lut_cnt].seg_map[seg_cnt].evnt_info_cnt = nvm_evnt_buff[evnt_offset_cnt];
							cpy_size 		= nvm_evnt_buff[evnt_offset_cnt]*sizeof(conops_sch_evnt_info_s);
							evnt_offset_cnt++;
							_evnt_buff = os_malloc(cpy_size);
							os_memcpy(_evnt_buff,&nvm_evnt_buff[evnt_offset_cnt],cpy_size);
							conops_sch_lut_info[lut_cnt].seg_map[seg_cnt].evnt_buff = _evnt_buff;
						}
					}
					else
					{
						os_memset(nvm_evnt_buff,0,6144);
						nvm_parameter_write(NVM_DATA,CONOPS_SCH_EVNT_BUFF_0+lut_cnt,&nvm_evnt_buff[0]);

						conops_sch_evnt_pending_sts = CONOPS_SCH_LUT_STS_IDLE;
						nvm_parameter_write(NVM_DATA,CONOPS_SCH_EVNT_PENDING_STS,(uint8_t*)&conops_sch_evnt_pending_sts);

						conops_sch_lut_info[lut_cnt].cmpl_seg_bin 	    = 0;
						conops_sch_lut_info[lut_cnt].crnt_evnt_cnt	    = 0;
						conops_sch_lut_info[lut_cnt].crnt_seg_cnt 	    = 0;
						conops_sch_lut_info[lut_cnt].grp_sts  		    = 0;
						conops_sch_lut_info[lut_cnt].rcd_seg_bin		= 0;
						conops_sch_lut_info[lut_cnt].totl_seg 		    = 0;
						conops_sch_lut_info[lut_cnt].totl_seg_bin		= 0;
						conops_sch_lut_info[lut_cnt].seg_map 			= NULL;
						nvm_parameter_write(NVM_DATA,CONOPS_SCH_LUT_INFO_0+lut_cnt,(uint8_t*)&conops_sch_lut_info[lut_cnt]);
					}
				}
			}
			lut_cnt++;
		}


		if(conops_sch_evnt_pending_sts & ((uint8_t)1<<sch_crnt_lut_cnt))
		{
			conops_sch_send_ipc_msg_pld(ORBIT_CONOPS_SCHEDULER,0,CONOPS_SCH_LUT_STRT,&sch_crnt_lut_cnt,1);
		}
		//if(nvm_evnt_buff != NULL)
		//	os_free(nvm_evnt_buff);
	}
	else
	{
		sch_crnt_lut_cnt = CONOPS_SCH_LUT_STS_IDLE;
		nvm_parameter_write(NVM_DATA,CONOPS_SCH_CRNT_EVNT,&sch_crnt_lut_cnt);
		sch_crnt_lut_cnt = 0;
	}
}

/**
 * @brief This API copies data from NVM memory to LUT buffer and trigger LUT start
 *
 */

void conops_sch_proc_init()
{
	uint8_t i =0;
#ifdef EXT_LUT_RAM
	nvm_evnt_buff = os_malloc_eram(6144);
#else
	nvm_evnt_buff = os_malloc(6144);
#endif

	os_memset(nvm_evnt_buff,0,6144);
	conops_sch_timer_init();

	while(i<SCH_GRP_ID_MAX_CNT)
		conops_sch_lut_info_segmnt_copy_prog[i++] = 0;

	for(i=0;i<SCH_GRP_ID_MAX_CNT;i++)
	{
		conops_sch_lut_info[i].cmpl_seg_bin 	= 0;
		conops_sch_lut_info[i].crnt_evnt_cnt	= 0;
		conops_sch_lut_info[i].crnt_seg_cnt 	= 0;
		conops_sch_lut_info[i].grp_sts  		= 0;
		conops_sch_lut_info[i].rcd_seg_bin		= 0;
		conops_sch_lut_info[i].totl_seg 		= 0;
		conops_sch_lut_info[i].totl_seg_bin		= 0;
		conops_sch_lut_info[i].seg_map 			= NULL;
	}

#ifndef LINUX_TEMP_PORT
	if(reset_cause !=  5)//RESET_CAUSE_POWER_ON_POWER_DOWN_RESET)
		conops_sch_lut_info_copy_from_nvm();
	else
	{

	}
#endif

#ifdef SCH_FIRST_TRIG_EN
	check_first_trig != SCH_OBC_SYNC_EVNT_STOP
#endif

}

/**
 * @brief This API starts predefined commissioning sequence when ground synchronization is delayed by 120mins.
 *		 Start and stop request of commissioning.
 */
#ifdef SCH_FIRST_TRIG_EN
/**
 * @brief callback for initial commissioning timer expired
 *
 */

void conops_sch_sat_int_tmr_cb()
{
	os_itc_msg_handle_t sch_send_ipc;
	sch_send_ipc.src_entity = ORBIT_CONOPS_SCHEDULER;
	sch_send_ipc.pld_info 	  = 0;
	sch_send_ipc.Msg_len	  = 0;
	sch_send_ipc.pld.pld_ptr  =  0;
	sch_send_ipc.Msg_id = SCH_ADCS_FALL_BACK;
	os_itc_msg_send(&sch_send_ipc, ADCS_CONTROLLER, os_send_itc_wait);
}


void conops_sch_obc_sync_evnt_start()
{
	uint32_t secs_cnt;
	uint8_t data = 1;

	nvm_parameter_read(NVM_DATA,RSVD_BIT_21,&check_first_trig);

	if(check_first_trig != SCH_OBC_SYNC_EVNT_STOP)
	{

		if(check_first_trig != SCH_OBC_SYNC_EVNT_STRT)
		{
			secs_cnt = 7200; //120 minutes (120*60)
			check_first_trig = SCH_OBC_SYNC_EVNT_STRT;

			time_t timeepoch = get_crnt_time_date_in_epoch();
			uint8_t *ptr_temp = (uint8_t*)&timeepoch;
			timeepoch += secs_cnt;
			nvm_parameter_write(NVM_DATA,RSVD_BIT_22,&ptr_temp[0]);
			nvm_parameter_write(NVM_DATA,RSVD_BIT_23,&ptr_temp[1]);
			nvm_parameter_write(NVM_DATA,RSVD_BIT_24,&ptr_temp[2]);
			nvm_parameter_write(NVM_DATA,RSVD_BIT_25,&ptr_temp[3]);

			nvm_parameter_write(NVM_DATA,RSVD_BIT_21,&check_first_trig);
#ifdef SCH_PRINT_EN
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat"
			DEBUG_CPRINT(("90mins Timer first start %ld diff %lu\n",timeepoch, secs_cnt));
			log_id_with_two_arg(LOG_INFO_L2,LOG_SCHEDULER,_90MINS_TIMER_FIRST_START__u64_DIFF__u32_,timeepoch,secs_cnt);
#pragma GCC diagnostic pop
#endif
		}
		else
		{
			uint8_t temp_ptr[8]={0};
			time_t *timeepoch_tmp = (time_t*)&temp_ptr[0];
			nvm_parameter_read(NVM_DATA,RSVD_BIT_22,&temp_ptr[0]);
			nvm_parameter_read(NVM_DATA,RSVD_BIT_23,&temp_ptr[1]);
			nvm_parameter_read(NVM_DATA,RSVD_BIT_24,&temp_ptr[2]);
			nvm_parameter_read(NVM_DATA,RSVD_BIT_25,&temp_ptr[3]);

			secs_cnt = *timeepoch_tmp - get_crnt_time_date_in_epoch();

#ifdef SCH_PRINT_EN
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat"
			DEBUG_CPRINT(("90mins Timer after restart  %ld diff %lu\n",*timeepoch_tmp, secs_cnt));
			log_id_with_two_arg(LOG_INFO_L2,LOG_SCHEDULER,_90MINS_TIMER_AFTER_RESTART__u64_DIFF__u32_,*timeepoch_tmp,secs_cnt);
#pragma GCC diagnostic pop
#endif
		}

		secs_cnt *= 1000; // convert to ticks

		os_timer_create(&conops_sch_sat_init_tmr,"sch_sat",ONESHOT,conops_sch_sat_int_tmr_cb,NULL);
		os_timer_start(conops_sch_sat_init_tmr,secs_cnt);

#ifdef SCH_PRINT_EN
		DEBUG_CPRINT(("OBC_SAT_SYNC_TMR_START\n"));
		log_id(LOG_INFO_L1,LOG_SCHEDULER,OBC_SAT_SYNC_TMR_START);

#endif
		conops_sch_send_ipc_msg_pld(ORBIT_CONOPS_SCHEDULER,0,CONOPS_SCH_LUT_STRT,&data,1);
	}
}


/**
 * @brief This API stop predefined commissioning sequence when ground synchronization is established.
 *		 Start and stop request of commissioning.
 */

void conops_sch_obc_sync_evnt_stop()
{
	uint8_t tmp_data = SCH_OBC_SYNC_EVNT_STOP;
	nvm_parameter_read(NVM_DATA,RSVD_BIT_21,&check_first_trig);
	if(check_first_trig == SCH_OBC_SYNC_EVNT_STRT)
	{
#ifdef SCH_PRINT_EN
		DEBUG_CPRINT(("OBC_SAT_SYNC_TMR_STOP\n"));
		log_id(LOG_INFO_L2,LOG_SCHEDULER,OBC_SAT_SYNC_TMR_STOP);
#endif
		os_timer_stop(conops_sch_sat_init_tmr);
		os_timer_delete(conops_sch_sat_init_tmr);
		nvm_parameter_write(NVM_DATA,RSVD_BIT_21,&tmp_data);
	}

}

#endif


/**
 * @brief cononps scheduler thread that handles state machine which manages LUT reception and  execution of the events
 *
 * Execution of the events include:
 * 1.Start
 * 2.Pause
 * 3.Stop
 * 4.Erase
 *
 */

void *conops_sch_proc()
{
	os_itc_msg_handle_t sch_itc_msg;
	uint8_t tmp_val;
	conops_sch_proc_init(); //////To DO :   can be disabled after proper obc init request recieved

	while(1)
	{
		os_itc_msg_rcv(ORBIT_CONOPS_SCHEDULER, &sch_itc_msg,os_wait_forever);

		switch( sch_itc_msg.src_entity)
		{
		case  OBC_MAIN:
		{
			switch(sch_itc_msg.Msg_id)
			{
			case OBC_SCH_INIT_REQ:
				//conops_sch_proc_init(); //////// To DO :   can be enabled after proper obc init request recieved
				if(conops_sch_obc_deinit ==1)
				{
					conops_sch_timer_init();
					conops_sch_obc_deinit = 0;
				}

				if((conops_sch_lut_grp_crnt_num != CONOPS_SCH_LUT_STS_IDLE) && (conops_sch_evnt_pending_sts & ((uint8_t)1<<conops_sch_lut_grp_crnt_num)))
				{
					if(conops_sch_lut_info[conops_sch_lut_grp_crnt_num].grp_sts == SCH_LUT_EXEC_PAUSE)
						conops_sch_send_ipc_msg_pld(ORBIT_CONOPS_SCHEDULER,0,CONOPS_SCH_LUT_STRT,&conops_sch_lut_grp_crnt_num,1);
				}

#ifdef SCH_PRINT_EN
				DEBUG_CPRINT(("OBC_SCH_INIT_REQ\n"));
#endif
				log_id(LOG_INFO_L2,LOG_SCHEDULER,OBC__SCH_INIT_REQ);
				conops_sch_send_ipc_msg_pld(OBC_MAIN,0,SCH_OBC_INIT_RSP,NULL,0);
				break;

			case OBC_SCH_DEINIT_REQ:
				conops_sch_timer_deinit();
				if(conops_sch_lut_grp_crnt_num != CONOPS_SCH_LUT_STS_IDLE)
				{
					conops_sch_lut_info[conops_sch_lut_grp_crnt_num].grp_sts = SCH_LUT_EXEC_PAUSE;
					nvm_parameter_write(NVM_DATA,CONOPS_SCH_CRNT_EVNT,(uint8_t*)&conops_sch_lut_info[conops_sch_lut_grp_crnt_num]);
				}
				conops_sch_obc_deinit = 1;
				conops_sch_send_ipc_msg_pld(OBC_MAIN,0,SCH_OBC_DEINIT_RSP,NULL,0);

#ifdef SCH_PRINT_EN
				DEBUG_CPRINT(("OBC_SCH_DEINIT_REQ\n"));
#endif
				log_id(LOG_INFO_L1,LOG_SCHEDULER,OBC__SCH_DEINIT_REQ);

				break;

#ifdef SCH_FIRST_TRIG_EN
			case OBC_SCH_INIT_SYNC_TIME_REQ:
				conops_sch_obc_sync_evnt_start();
				break;

			case OBC_SCH_STOP_SYNC_TIME_REQ:
				conops_sch_obc_sync_evnt_stop();
				//check_first_trig = SCH_OBC_SYNC_EVNT_STOP;
				break;
#endif

			}
		}
		break;

		case ORBIT_CONOPS_SCHEDULER:
		{
			switch(sch_itc_msg.Msg_id)
			{
			case CONOPS_SCH_LUT_COPY:
				conops_sch_lut_info_copy(sch_itc_msg.pld.pld_ptr);
				break;

			case CONOPS_SCH_LUT_SAVE:

			case CONOPS_SCH_LUT_SAVE_STRT:
				conops_sch_lut_grp_crnt_num = *((uint8_t*)sch_itc_msg.pld.pld_ptr);

				if(conops_sch_lut_info[conops_sch_lut_grp_crnt_num].grp_sts  != SCH_LUT_IDLE)
				{
					conops_sch_lut_info_copy_to_nvm(conops_sch_lut_grp_crnt_num);
				}

				if(sch_itc_msg.Msg_id == CONOPS_SCH_LUT_SAVE)
					break;

			case CONOPS_SCH_LUT_STRT:

				tmp_val = *((uint8_t*)sch_itc_msg.pld.pld_ptr);

				if(conops_sch_lut_info[tmp_val].grp_sts  != SCH_LUT_IDLE)
				{
					conops_sch_lut_grp_crnt_num = tmp_val;
					conops_sch_lut_info[conops_sch_lut_grp_crnt_num].grp_sts  	= SCH_LUT_EXEC_PROG;
					nvm_parameter_write(NVM_DATA,CONOPS_SCH_CRNT_EVNT,(uint8_t*)&conops_sch_lut_grp_crnt_num);

#ifdef SCH_PRINT_EN
					DEBUG_CPRINT(("SCH_LUT_STRT-[%d]\n",conops_sch_lut_grp_crnt_num));
#endif
					log_id_with_one_arg(LOG_INFO_L2,LOG_SCHEDULER,LUT_STRT__u8_,conops_sch_lut_grp_crnt_num);

				}
				else
					break;

			case CONOPS_SCH_EVNT_NXT_TMR:
				if(conops_sch_lut_grp_crnt_num != CONOPS_SCH_LUT_STS_IDLE)
				{
					if(conops_sch_lut_info[conops_sch_lut_grp_crnt_num].grp_sts == SCH_LUT_EXEC_PROG)
					{
						if(conops_sch_lut_info_segmnt_copy_prog[conops_sch_lut_grp_crnt_num] == 0)
							conops_sch_check_next_evnt(&conops_sch_lut_info[conops_sch_lut_grp_crnt_num],conops_sch_lut_grp_crnt_num);
					}
				}
				break;

			case CONOPS_SCH_LUT_STOP:
				os_timer_stop(conops_sch_evnt_tmr);
			case CONOPS_SCH_LUT_ERASE:
			case CONOPS_SCH_LUT_CMPLT:
				tmp_val = *((uint8_t*)sch_itc_msg.pld.pld_ptr);

#ifdef SCH_PRINT_EN
				DEBUG_CPRINT(("SCH_LUT_EXEC_CMPLT[%u]\n",tmp_val));
#endif
				log_id_with_one_arg(LOG_INFO_L2,LOG_SCHEDULER,LUT_EXEC_CMPLT_u8_,tmp_val);

#ifdef	SCH_FIRST_TRIG_EN
				if((check_first_trig == SCH_OBC_SYNC_EVNT_STRT) && (tmp_val==1))
				{
					conops_sch_lut_info[tmp_val].grp_sts  = SCH_LUT_RDY;
				}
				else
#endif
				{
					conops_sch_lut_free(tmp_val);
				}

				if(conops_sch_lut_grp_crnt_num == tmp_val)
				{
					conops_sch_lut_grp_crnt_num = CONOPS_SCH_LUT_STS_IDLE;
					nvm_parameter_write(NVM_DATA,CONOPS_SCH_CRNT_EVNT,(uint8_t*)&conops_sch_lut_grp_crnt_num);
				}

				break;

			case CONOPS_SCH_EVNT_EXEC:
				if(conops_sch_crnt_evnt != NULL)
				{
					conops_sch_trig_event(conops_sch_crnt_evnt);
					os_free(conops_sch_crnt_evnt);
					conops_sch_crnt_evnt = NULL;
				}
				conops_sch_send_ipc_msg_pld(ORBIT_CONOPS_SCHEDULER,0,CONOPS_SCH_EVNT_NXT_TMR,NULL,0);
				break;

			case CONOPS_SCH_LUT_PAUSE:
			{
				conops_sch_lut_info[conops_sch_lut_grp_crnt_num].grp_sts = SCH_LUT_EXEC_PAUSE;
				conops_sch_lut_grp_crnt_num = CONOPS_SCH_LUT_STS_IDLE;
				nvm_parameter_write(NVM_DATA,CONOPS_SCH_CRNT_EVNT,(uint8_t*)&conops_sch_lut_grp_crnt_num);
				os_timer_stop(conops_sch_evnt_tmr);
			}
			break;
			}
		}
		break;
		}

		if(sch_itc_msg.pld.pld_ptr != NULL)
		{
			os_free(sch_itc_msg.pld.pld_ptr);

			sch_itc_msg.pld.pld_ptr = NULL;
		}
	}
}



/**
 * @brief This API executes the given scheduler LUT event - It sends IPC message to the corresponding module with event infomation to be 
executed
 *
 * @param[in]  _sch_evnt : structure pointer gives value of event to be executed
 *
 */

void conops_sch_trig_event(conops_sch_evnt_s *_sch_evnt)
{
	os_itc_msg_handle_t sch_send_ipc;
	sch_send_ipc.src_entity   		= _sch_evnt->src_id;

	if(_sch_evnt->id>TC_TM_MAX_ID)
	{
		sch_send_ipc.Msg_id 	  	= _sch_evnt->id;
		sch_send_ipc.Msg_len	  	= 8;
		sch_send_ipc.pld.pld_ptr 	= os_malloc(8);
		os_memcpy(sch_send_ipc.pld.pld_ptr,&_sch_evnt->arg1,4);
		os_memcpy(sch_send_ipc.pld.pld_ptr + 4,&_sch_evnt->arg2,4);
	}
	else
	{
		sch_send_ipc.Msg_id 	  	= TC_SCH_LUT_TC_TRIG;
		sch_send_ipc.Msg_len	  	= sizeof(conops_sch_evnt_s);
		sch_send_ipc.pld.pld_ptr 	= os_malloc(sch_send_ipc.Msg_len);
		os_memcpy(sch_send_ipc.pld.pld_ptr,_sch_evnt,sch_send_ipc.Msg_len);
		_sch_evnt->dest_id = TC_TM_MANAGER_IPC_RECEIVE;


	}


	if(os_itc_msg_send(&sch_send_ipc,_sch_evnt->dest_id,os_send_itc_wait) != ral_success)
	{
#ifdef SCH_PRINT_EN
		DEBUG_CPRINT(("SCH ITC Message send fail\n"));
#endif
		log_id(LOG_ERROR,LOG_SCHEDULER,OBC_APP_ITC_MESSAGE_SEND_FAIL);
		os_free(sch_send_ipc.pld.pld_ptr);
		sch_send_ipc.pld.pld_ptr = NULL;
	}

#ifdef SCH_PRINT_EN
		DEBUG_CPRINT(("SCH_EVNT_TRG_CMPLT\n"));
#endif

}



