#include "sch_parser.h"
#include "eps_tc_tm.h"
#include "mfcc_tc_tm_sample.h"
#include "tc_tm_lib_common.h"

conops_sch_evnt_info_s evnt_buff_g[SCH_MAX_EVENT_PER_LUT];
uint32_t sch_ev_exec_time_sec_arr[SCH_MAX_EVENT_PER_LUT];
uint32_t tot_num_evnts = 0;
uint32_t evcnt = 0;
conops_sch_evnt_info_s *cur_evnt_info_p = NULL;
uint8_t  tot_seg_cnt;
uint8_t  sch_crnt_lut_grp_id = 0;
uint64_t seg_data_arr[SCH_MAX_SEG_PER_LUT]; // Store individual segment start address
uint32_t seg_size_arr[SCH_MAX_SEG_PER_LUT]; // Store individual segment byte size
uint8_t  seg_tx_sts_arr[SCH_MAX_SEG_PER_LUT] = {0};
uint8_t  seg_tx_sts_arr_tm_sts = {0};
uint8_t  seg_tx_en=0;
extern s_sock_info tctm_soc_inf;
uint64_t seg_tx_sts[3];

conops_sch_evnt_info_s *sch_ev_info_p_g = (conops_sch_evnt_info_s*) evnt_buff_g;
conops_sch_evnt_info_s temp_sch_ev_info_p_g;
static uint32_t sch_tc_tm=0;

uint8_t   conops_sch_tx_sts=0;
uint8_t   scheduler_lut_num=0;
uint64_t  scheduler_seg_tx_sts=0;
extern uint8_t radio_mod_id ;

conops_sch_lut_info_gs  conops_sch_lut_info[SCH_MAX_LUT_CNT];

uint8_t key[] = {0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
		0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
		0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
		0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
		0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
		0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
		0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
		0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
		0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
		0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
		0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
		0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
		0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
		0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
		0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
		0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};

uint8_t iv[16] = {0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};


uint8_t sch_prsr_init(uint8_t lut_grp_id)
{
	FILE *fp_conops;
	char *line_buff = NULL;
	size_t dummy_line_len = 0;
	ssize_t line_len = 0;
	sch_crnt_lut_grp_id = lut_grp_id;
	tot_num_evnts = 0;
	evcnt = 0;

	fp_conops = fopen(SCH_TC_FILE, "r");

	if (fp_conops == NULL) {
		printf("ERROR[-] Unable to open the file\n"); exit(1);
	}

	/* Read file line by line and extract event information */
	while ((line_len = getline(&line_buff, &dummy_line_len, fp_conops)) != -1) {
		extract_event_info(line_buff);
	}

	printf("\nTotal SCH events count %u\n",tot_num_evnts);

	if(SCH_MAX_EVENT_PER_LUT < tot_num_evnts) {
		printf("Error[-]Schedular TOTAL EVNT CNT [%u] > MAX EVNT CNT[ %u]\n",tot_num_evnts,SCH_MAX_EVENT_PER_LUT);
		exit(1);
	}

	/* Free line buffer allocated by c library function and close file pointer */
	free(line_buff);
	fclose(fp_conops);


	//	sort_sch_events_exec_order();
	sch_pack_event_in_seg(tot_num_evnts, SCH_RDY_EXEC);

	return 0;
}

/* Parse each line and extract event information and event execution time */
void extract_event_info(char* _line_buff)
{
	char *sub_str; char* str = _line_buff; char *rem_str = _line_buff;
	uint8_t  tmp_u8=0;
	uint16_t tmp_u16=0;
	uint32_t tmp_u32=0;
	uint32_t delay = 0;

	//Drop frame info
	sub_str = strtok_r(str, ",", &rem_str);
	//delay
	sub_str = strtok_r(rem_str, ",", &rem_str);
	tmp_u32 = strtoul(sub_str, NULL, 16);
	delay = tmp_u32;
	//offset
	sub_str = strtok_r(rem_str, ",", &rem_str);
	tmp_u32 = strtoul(sub_str, NULL, 16);
	sch_ev_info_p_g[evcnt].arg1 = tmp_u32;

	//length
	sub_str = strtok_r(rem_str, ",", &rem_str);
	tmp_u16 = strtoul(sub_str, NULL, 16);
	sch_ev_info_p_g[evcnt].arg2 = tmp_u16;

	//dest_id
	sub_str = strtok_r(rem_str, ",", &rem_str);
	tmp_u8 = strtoul(sub_str, NULL, 16);
	sch_ev_info_p_g[evcnt].dest_id = tmp_u8;

	//tc_id
	sub_str = strtok_r(rem_str, ",", &rem_str);
	tmp_u16 = strtoul(sub_str, NULL, 16);
	sch_ev_info_p_g[evcnt].id = tmp_u16;

	if(tmp_u16 <  TC_TM_MAX_ID)
		sch_ev_info_p_g[evcnt].src_id = TC_SRC_GS;
	else
		sch_ev_info_p_g[evcnt].src_id = ORBIT_CONOPS_SCHEDULER;

	if(evcnt==0)
	{
		sch_tc_tm  = time(NULL);

	}

	sch_ev_info_p_g[evcnt].epoch =  sch_tc_tm + delay;
	sch_tc_tm = sch_ev_info_p_g[evcnt].epoch;
	sch_ev_exec_time_sec_arr[evcnt]= sch_ev_info_p_g[evcnt].epoch;


#if 0
	print_raw_event_info(&sch_ev_info_p_g[evcnt]);
#endif

	evcnt++;
	tot_num_evnts = evcnt;
}



void print_raw_event_info(conops_sch_evnt_info_s *_conops_sch_evnt_info)
{
	printf("\nUTC=%d\tSrc=%.3d\tDest=%.3d\tEvnt=%.5d\tData1=%.6d\t\tData2=%d",\
			_conops_sch_evnt_info->epoch,\
			_conops_sch_evnt_info->src_id,\
			_conops_sch_evnt_info->dest_id,\
			_conops_sch_evnt_info->id,\
			_conops_sch_evnt_info->arg1,\
			_conops_sch_evnt_info->arg2);
}


/* Pack all the scheduler events in segments.
 * Segmentation is required to overcome TC payload size restriction of 426 bytes
 */
void sch_pack_event_in_seg(uint32_t _tot_num_ev, uint8_t _exec_wait_ste)
{
	uint8_t seg_num;
	uint32_t cur_seg_size;
	conops_sch_lut_info_s *sch_lut_seg_p = NULL;
	cur_evnt_info_p = (conops_sch_evnt_info_s*) evnt_buff_g;
	uint32_t num_evnts_in_cur_seg = 0;
	conops_sch_evnt_info_s *tmp_evnt_p = NULL;
	uint32_t loop;

	tot_seg_cnt = ((_tot_num_ev / SCH_MAX_EVNT_PER_SEG) + ((_tot_num_ev % SCH_MAX_EVNT_PER_SEG) ? 1: 0));

	for (seg_num = 0; seg_num < tot_seg_cnt; seg_num++)
	{
		// When Current Segment is not the last one
		if(seg_num  != tot_seg_cnt - 1) {
			// Calculate num events in all seg other than last and seg size
			num_evnts_in_cur_seg = SCH_MAX_EVNT_PER_SEG;
			cur_seg_size = (sizeof(conops_sch_lut_info_s) - sizeof(sch_lut_seg_p->evnt_info_p) + \
					((num_evnts_in_cur_seg) * sizeof(conops_sch_evnt_info_s)));
		}
		// When Current segment is the last segment
		else {
			// Calculate num events in last seg and last seg size
			num_evnts_in_cur_seg = _tot_num_ev % SCH_MAX_EVNT_PER_SEG;
			cur_seg_size = sizeof(conops_sch_lut_info_s) - sizeof(sch_lut_seg_p->evnt_info_p) + \
					((num_evnts_in_cur_seg) * sizeof(conops_sch_evnt_info_s));
		}
		// Update the Segment with Schedule evnt information
		sch_lut_seg_p = (conops_sch_lut_info_s*)malloc(cur_seg_size);
		sch_lut_seg_p->lut_grp_id    = sch_crnt_lut_grp_id;
		sch_lut_seg_p->tot_seg       = tot_seg_cnt;
		sch_lut_seg_p->crnt_seg_id   = seg_num;
		sch_lut_seg_p->trig_type     = _exec_wait_ste;
		sch_lut_seg_p->num_evnt      = num_evnts_in_cur_seg;
		sch_lut_seg_p->evnt_info_p   = (conops_sch_evnt_info_s*)(((uint8_t*)sch_lut_seg_p) + 5);

		memcpy((void*)sch_lut_seg_p->evnt_info_p, (void*)cur_evnt_info_p, (num_evnts_in_cur_seg * sizeof(conops_sch_evnt_info_s)));
		cur_evnt_info_p             += num_evnts_in_cur_seg;

		seg_size_arr[seg_num] = cur_seg_size;
		seg_data_arr[seg_num] = (uint64_t)sch_lut_seg_p;

		/* Print Information */
		printf("\nSCH TX Info======>\nGroup ID %hhu\tSegment:  %hhu / %hhu", sch_lut_seg_p->lut_grp_id, sch_lut_seg_p->crnt_seg_id,sch_lut_seg_p->tot_seg);
		//printf("Segment Trigger type %hhu\n", sch_lut_seg_p->trig_type);
		printf("\tEvent Count %hhu\n", sch_lut_seg_p->num_evnt);
		tmp_evnt_p =(conops_sch_evnt_info_s*) ((uint8_t*)sch_lut_seg_p+5);
		for(loop = 0; loop< sch_lut_seg_p->num_evnt; loop++) {
			print_raw_event_info(tmp_evnt_p);
			tmp_evnt_p++;
		}
	}
}



#if 0
void sort_sch_events_exec_order(void)
{
	int n = tot_num_evnts;
	uint32_t temp_sec = 0;
	int i,j;
	for (i = 0; i < n-1; i++) {
		for (j = 0; j < n-i-1; j++) {
			if (sch_ev_exec_time_sec_arr[j] > sch_ev_exec_time_sec_arr[j+1]) {

				temp_sec = sch_ev_exec_time_sec_arr[j];
				sch_ev_exec_time_sec_arr[j] = sch_ev_exec_time_sec_arr[j+1];
				sch_ev_exec_time_sec_arr[j+1] = temp_sec;

				temp_sch_ev_info_p_g.epoch = sch_ev_info_p_g[j].epoch;
				temp_sch_ev_info_p_g.src_id = sch_ev_info_p_g[j].src_id;
				temp_sch_ev_info_p_g.dest_id = sch_ev_info_p_g[j].dest_id;
				temp_sch_ev_info_p_g.id = sch_ev_info_p_g[j].id;
				temp_sch_ev_info_p_g.arg1 = sch_ev_info_p_g[j].arg1;
				temp_sch_ev_info_p_g.arg2 = sch_ev_info_p_g[j].arg2;

				sch_ev_info_p_g[j].epoch = sch_ev_info_p_g[j+1].epoch;
				sch_ev_info_p_g[j].src_id = sch_ev_info_p_g[j+1].src_id;
				sch_ev_info_p_g[j].dest_id = sch_ev_info_p_g[j+1].dest_id;
				sch_ev_info_p_g[j].id = sch_ev_info_p_g[j+1].id;
				sch_ev_info_p_g[j].arg1 = sch_ev_info_p_g[j+1].arg1;
				sch_ev_info_p_g[j].arg2 = sch_ev_info_p_g[j+1].arg2;

				sch_ev_info_p_g[j+1].epoch=temp_sch_ev_info_p_g.epoch;
				sch_ev_info_p_g[j+1].src_id = temp_sch_ev_info_p_g.src_id;
				sch_ev_info_p_g[j+1].dest_id = temp_sch_ev_info_p_g.dest_id;
				sch_ev_info_p_g[j+1].id = temp_sch_ev_info_p_g.id;
				sch_ev_info_p_g[j+1].arg1 = temp_sch_ev_info_p_g.arg1;
				sch_ev_info_p_g[j+1].arg2 = temp_sch_ev_info_p_g.arg2;
			}
		}
	}
}

#endif


uint8_t conops_sch_tx_frame(uint32_t tc_id, uint16_t size,uint8_t *data)
{
    s_tc_frame *tc_orig_app;
    s_crypt_params param;
    uint8_t *dst;
    uint32 loop = 0;
    int32 port = atoi(tctm_soc_inf.port_num);
    int32 addr = inet_addr(tctm_soc_inf.ip_addr);
    /* Encryption related params */
    uint8 key[] = {0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
        0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
        0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
        0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
        0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
        0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
        0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
        0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
        0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
        0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
        0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
        0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
        0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
        0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
        0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
        0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};


    uint8 iv[16] = {0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};

    /* Send buffer and frame memory allocations */
    tc_orig_app = (s_tc_frame *) malloc(sizeof(s_tc_frame));
    dst = (unsigned char *) malloc(MAX_TC_BUFF_SIZE);

    /* The above part need to be built in the Go Language */

    /* From here onwards TC TM library is used */
    /* Initialize telecommand structure instance */
    tc_orig_init(tc_orig_app);
    /* Configure Start of Frame */
    tc_orig_cfg_sof(tc_orig_app, TC_TM_LIB_SOF1, TC_TM_LIB_SOF2);
    /* Configure Satellite ID */
    tc_orig_cfg_sat_id(tc_orig_app, RECV_SAT_ID);
    /* Configure Ground station ID */
    tc_orig_cfg_gs_id(tc_orig_app, SOURCE_GROUND_STN_ID);
    /* Enable encryption */
    tc_orig_cfg_tc_ctrl(tc_orig_app, CRYPTO_ENCRYP_ENBL);
    /* Configure Quality of Service */
    tc_orig_cfg_qos(tc_orig_app, TC_QOS_CFG);
    /* Configure source address */
    tc_orig_cfg_sa_id(tc_orig_app, TC_SRC_GS);
    /* Configure Radio Module ID */
    tc_orig_cfg_rm_id(tc_orig_app,radio_mod_id);

    printf("\n TC Radio ID: %d, %d",radio_mod_id,tc_orig_app->rm_id);
    /* Configure destination address */
    tc_orig_cfg_da_id(tc_orig_app, TC_DST_OBC);
    tc_orig_cfg_eof(tc_orig_app, TC_TM_LIB_EOF);


	/* Configure Telecommand ID */
	tc_orig_cfg_tc_id(tc_orig_app, tc_id);
	/* Configure Telecommand Length */
	tc_orig_cfg_tc_len(tc_orig_app, size);
	/* Configure Telecommand payload */
	tc_orig_cfg_tc_data (tc_orig_app,data);

	/* Configure Encryption parameters */
	tc_orig_app->cmac_hmac = (uint8_t *) malloc(SHA256_HASH_SIZE);
	memcpy(param.iv, iv, 16);
	param.key_size = 256;
	param.key = (unsigned char *)malloc(param.key_size);
	memcpy(param.key, key, param.key_size);
	param.encrypt_mode = CRYPT_AES_CFB8;
	tc_orig_select_encryption(&param);

	/* Generate Telecommand as binary data stream */
	size = tc_pack(dst, tc_orig_app);

	printf("MFCC APP: Transmitted TC byte stream: ");
	for(loop = 0; loop < size; loop++)
		printf("%x ", dst[loop]);
	printf("\n");

	/* Send generated Telecommand via socket interface */
	mfcc_tcp_send(addr, port, dst, size);
	return 0;
}


void conops_sch_print_tx_seg()
{
	uint16_t i=0;
printf("\n**********************************\n");
	printf("\nCONOPS_SCH_TX_INFO==>\nSEG_TC_SENT\t");

	for(i=tot_seg_cnt;i>=0;i--)
	{
		if(seg_tx_sts[0] & (1<<i))
			printf("1");
		else
			printf("0");
		if(i==0)
			break;
	}

	printf("\nSEG_TM_RCD\t");
	for(i= tot_seg_cnt;i>=0;i--)
	{
		if(seg_tx_sts[1] & (1<<i))
			printf("1");
		else
			printf("0");
		if(i==0)
			break;
	}
	printf("\nSEG_IN_OBC\t");

	for(i= tot_seg_cnt;i>=0;i--)
	{
		if(seg_tx_sts[2] & (1<<i))
			printf("1");
		else
			printf("0");
		if(i==0)
			break;
	}
printf("\n**********************************\n");
}


void conops_sch_seg_retransmit()
{
    uint8_t  seg_cnt = 0;
    uint8_t  status = 0;
    uint8_t  i = 0;

    while(i<SCH_SEG_RTRY_CNT)
    {
        i++;
        seg_tx_sts[1] |= seg_tx_sts[2];
        if(seg_tx_sts[0] != seg_tx_sts[1])
        {
            printf("Retransmission try:%d\n",i);
            for(seg_cnt = 0; seg_cnt < tot_seg_cnt; seg_cnt++)
            {
                if((seg_tx_sts[1] & ((uint64_t)0x0001 << seg_cnt)) == 0)
                {
                    seg_tx_en=1;
                    conops_sch_tx_frame(TC_CONOPS_SCH_LUT_CFG, seg_size_arr[seg_cnt],(uint8_t*)seg_data_arr[seg_cnt]);

                    sleep((float)SCH_DELAY_PER_TX_SEG / 1000);
                }
            }
        status = sch_crnt_lut_grp_id;
        conops_sch_tx_frame(TC_CONOPS_SCH_STS_INFO,1,&status);
        sleep(1);
        }
        else
        {
            break;
        }

    }
}


uint8_t conops_sch_tc(uint32_t tc_id, uint8_t** tc_data, uint16_t *tc_len)
{
	uint8_t status=0;
	uint8_t LUT_id=0;
	uint8_t  seg_cnt = 0;
	uint8_t* tc_data1;
	
	switch(tc_id)
	{
	case TC_CONOPS_SCH_LUT_CFG:
	{
		//only this case can send socket data and hence status is set.
		//This is required since this case will send back to back segmented TC packets
		status = 1;
#if 0
		printf("\n0.SCH_CONOPS_EVNT\n1.SCH_TC\nEnter trigger type:");
		scanf("%hhu",&sch_trig_type);
		if(sch_trig_type>1)
		{
			printf("\ninput error");
			break;
		}
#endif
		printf("\nEnter LUT number of Scheduler input: ");
		scanf("%hhu",&LUT_id);

		if( LUT_id > (SCH_MAX_LUT_CNT-1))
		{
			printf("\nERROR[-] Invalid id\n");
			break;
		}

		seg_tx_sts_arr_tm_sts=0;
		seg_tx_sts[0] = 0;
		seg_tx_sts[1] = 0;
		seg_tx_sts[2] = 0;

		for(seg_cnt = 0; seg_cnt < SCH_MAX_SEG_PER_LUT; seg_cnt++)
			seg_tx_sts_arr[seg_cnt]=0;

		sch_prsr_init(LUT_id);

		for(seg_cnt = 0; seg_cnt < tot_seg_cnt; seg_cnt++)
		{
                     seg_tx_en = 1;
			seg_tx_sts[0] |= 1<<seg_cnt;
			conops_sch_tx_frame(tc_id, seg_size_arr[seg_cnt],(uint8_t*)seg_data_arr[seg_cnt]);
			sleep((float)SCH_DELAY_PER_TX_SEG / 1000);
		}

		status = sch_crnt_lut_grp_id;
		conops_sch_tx_frame(TC_CONOPS_SCH_STS_INFO,1,&status);
		sleep(1);

		conops_sch_print_tx_seg();

		//check
		if(seg_tx_sts_arr_tm_sts)
		{
			conops_sch_seg_retransmit();
		}
		else
		{
			printf("\nNo segment transmitted to OBC, check OBC GS communication");
			status = -1;
		}


		//free all the segment
		for(seg_cnt = 0; seg_cnt < tot_seg_cnt; seg_cnt++)
		{
			free((void*)seg_data_arr[seg_cnt]);
			//seg_data_arr[seg_cnt] = NULL;
		}

		seg_tx_en = 0;
		seg_tx_sts_arr_tm_sts=0;
		seg_tx_sts[0] = 0;
		seg_tx_sts[1] = 0;
		seg_tx_sts[2] = 0;
                status =-1;

	}
	break;
	case TC_CONOPS_SCH_LUT_RUN_CTRL:
	{
		uint8_t i=0;

		*tc_len = 2;
		tc_data1 = (uint8_t *)malloc(*tc_len);
		for(i=0;i<SCH_MAX_LUT_CNT;i++)
		{
			printf("\n%hhu - LUT%hhu control",i,i);
		}
		printf("\nEnter your option: \n");
		scanf("\n%hhu",&tc_data1[0]);
		if(!(tc_data1[0] == 0 || tc_data1[0] == 1))
		{
			printf("Invalid Test ID\n");
			status = -1;
		}

		if(tc_data1[0] < SCH_MAX_LUT_CNT)
		{
			printf("Enter Scheduler Control Options: \n\
                            \r1 - Save\n\
                            \r2 - Start / Resume\n\
                            \r3 - Pause\n\
                            \r4 - Stop and erase LUT\n\
                            \r5 - Erase LUT\n");
			scanf("%hhu",&tc_data1[1]);
			if(tc_data1[1] > 5 || tc_data1[1] == 0)
			{
				printf("Invalid Test ID\n");
				status = -1;
			}
		}
		*tc_data = tc_data1;
	}
	break;

	case TC_CONOPS_SCH_STS_INFO:
	{

		*tc_len = 1;
		tc_data1 = (uint8_t *)malloc(*tc_len);

		for(uint8_t i=0; i<SCH_MAX_LUT_CNT; i++)
		{
			printf("\n%hhu - LUT%hhu ",i,i);
		}
		printf("\n%hhu - ALL STATUS\n",SCH_MAX_LUT_CNT);


		printf("Enter your option: \n");

		scanf("%hhu",&tc_data1[0]);

		if(tc_data1[0] <= SCH_MAX_LUT_CNT )
		{

			status = 0;
		}
		else
		{
			printf("Invalid Test ID\n");
			status = -1;
		}
		*tc_data = tc_data1;
	}
	break;
	}
	return status;

}


void conops_sch_tm_decode(uint32_t tm_id,uint8_t *tm_frame_tm_data,uint16_t tm_len)
{

	uint8_t sch_lut_cfg_rsp[3];
	switch(tm_id)
	{
	case TM_CONOPS_SCH_LUT_CFG:
	{
		memcpy(&sch_lut_cfg_rsp[0],tm_frame_tm_data,3);
		if(sch_lut_cfg_rsp[0]  && (tm_frame_tm_data[2] < SCH_MAX_LUT_CNT ))
		{
#if 0
			memcpy(&sch_lut_cfg_rsp,&tm_frame_tm_data[1],2);
			printf("Scheduler LUT configuration response\n");
			printf("Segment Count %hhu\n",sch_lut_cfg_rsp & 0xFF);
			printf("Group ID %hhu\n",(sch_lut_cfg_rsp >> 8));
#endif
			printf("CONOPS SCH LUT RX Grp-%hhu Seg%hhu - SUCCESS\n",tm_frame_tm_data[2],tm_frame_tm_data[1]);

			if(tm_frame_tm_data[2] == sch_crnt_lut_grp_id)
			{
				seg_tx_sts_arr_tm_sts++;
				seg_tx_sts_arr[tm_frame_tm_data[1]]=1;
				seg_tx_sts[1] |= 1<<tm_frame_tm_data[1];
			}
		}
		else
		{
			printf("INVALID CONOPS_SCH STATUS\n");
		}

	}
	break;

	case TM_CONOPS_SCH_LUT_RUN_CTRL:
	{

		if(tm_frame_tm_data[0])
			printf("Scheduler control failed - error code: %hhu\n",tm_frame_tm_data[0]);
		else
			printf("Scheduler control succeeded\n");

	}
	break;

	case TM_CONOPS_SCH_STS_INFO:
	{
		uint8_t cnt= 0, max_cnt=0,frame_len =0,cnt1=0;
		frame_len = sizeof(conops_sch_lut_info_gs);

		if(tm_frame_tm_data[0] < SCH_MAX_LUT_CNT)
		{
			cnt = tm_frame_tm_data[0];
			max_cnt = cnt;
			cnt1=0;
		}
		else
		{
			cnt = 0;
			cnt1 = 1;
			max_cnt = SCH_MAX_LUT_CNT;

		}
		do
		{

			if(cnt1)
			{
				os_memcpy(&conops_sch_lut_info[cnt], &tm_frame_tm_data[1+(cnt*frame_len)] ,frame_len);
			}
			else
			{
				os_memcpy(&conops_sch_lut_info[cnt], &tm_frame_tm_data[1] ,frame_len);
			}


			printf("\n***************\nStatus of LUT%d :", cnt);
			if(conops_sch_lut_info[cnt].grp_sts)
			{
				switch(conops_sch_lut_info[cnt].grp_sts)
				{
				case SCH_LUT_EXEC_CMPLT:
					printf("Execution Completed\n");
					break;
				case SCH_LUT_EXEC_STOP:
					printf("Execution Stopped\n");
					break;
				case SCH_LUT_EXEC_PAUSE:
					printf("Execution in Pause\n");
					break;
				case SCH_LUT_EXEC_PROG:
					printf("Execution in Progress\n");
					break;
				case SCH_LUT_RDY:
					printf("Events Ready to execute\n");
					break;
				case SCH_LUT_RX_PROG:
					printf("Events Receiving in Progress\n");
					break;
				default:
					printf("Invalid status\n");
					break;
				}
				printf("LUT%d Segment Info:\n",cnt);
				printf("Total Segment Count: %d\n",conops_sch_lut_info[cnt].totl_seg);
				uint8_t i=0;
				printf("Total  Segment in Binary\t: ");
				for(i= conops_sch_lut_info[cnt].totl_seg;i>=0;i--)
				{
					if(conops_sch_lut_info[cnt].totl_seg_bin & (1<<i))
						printf("1");
					else
						printf("0");
					if(i==0)
						break;
				}

				printf("\nRecvd  Segment in Binary\t: ");
				if(seg_tx_en)
				{
					seg_tx_sts[2] =conops_sch_lut_info[cnt].rcd_seg_bin;
                                         seg_tx_en = 0;
				}
				for(i= conops_sch_lut_info[cnt].totl_seg;i>=0;i--)
				{
					if(conops_sch_lut_info[cnt].rcd_seg_bin & (1<<i))
						printf("1");
					else
						printf("0");
					if(i==0)
						break;
				}

				printf("\nExectd Segment in Binary\t: ");
				for(i= conops_sch_lut_info[cnt].totl_seg;i>=0;i--)
				{
					if(conops_sch_lut_info[cnt].cmpl_seg_bin & (1<<i))
						printf("1");
					else
						printf("0");
					if(i==0)
						break;
				}

				if(conops_sch_lut_info[cnt].grp_sts == 4)
				{
					printf("\nCrnt exec seg count: %d\n",conops_sch_lut_info[cnt].crnt_seg_cnt);
					printf("Crnt event count: %d\n",conops_sch_lut_info[cnt].crnt_evnt_cnt);
				}
			}
			else
				printf("IDLE\n");


			cnt++;
		}while(cnt<max_cnt);
		printf("\n*****************\n");
	}

	break;
	}

}
