/**
 * @file eps.c
 *
 * @brief This file contains APIs for EPS driver
 *
 * The functions provided in the file encodes and decodes EPS frame for different command set
 *
 * @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 "exo_osal.h"
#include "exo_io_al_i2c_common.h"
#include "eps.h"
#include "exo_io_al_sos_timer.h"
#include "exo_common.h"
#include "log_eps.h"
#include "logger.h"
#include "obc_tc_tm.h"
#include "eps_ctrlr_init.h"
#include "exo_tctm_ipc.h"
#include "err_handler.h"


#define EPS_CHNL_OFF(x,y)  (x = x&~(1<<y))
#define EPS_CHNL_ON(x,y)  (x = x|(1<<y))
#define EPS_GET_CHNL(x,y) (x&1<<y)>0?1:0
#ifdef JANUS2
extern ioal_i2c_hdle ioal_hi2c3;
#else
extern ioal_i2c_hdle ioal_hi2c1;
#endif

/// counter to check number of CRC failure observed during EPS frame transaction
uint16_t eps_crc_cnt[2]={0,0};

/// array containing calculated CRC values
static const uint8_t CRC_Table[256]={0,7,14,9,28,27,18,21,56,63,54,49,
    36,35,42,45,112,119,126,121,
    108,107,98,101,72,79,70,65,84,83,90,93,224,231,238,233,252,251,
    242,245,216,223,214,209,196,195,202,205,144,151,158,153,140,139,
    130,133,168,175,166,161,180,179,186,189,199,192,201,206,219,220,
    213,210,255,248,241,246,227,228,237,234,183,176,185,190,171,172,165,
    162,143,136,129,134,147,148,157,154,39,32,41,46,59,60,53,50,31,24,17,22,
    3,4,13,10,87,80,89,94,75,76,69,66,111,104,97,102,115,116,125,122,137,142,
    135,128,149,146,155,156,177,182,191,184,173,170,163,164,249,254,247,240,
    229,226,235,236,193,198,207,200,221,218,211,212,105,110,103,96,117,114,123,124,81,86,
    95,88,77,74,67,68,25,30,23,16,5,2,11,12,33,38,47,40,61,58,51,52,78,73,64,71,82,85,92,
    91,118,113,120,127,106,109,100,99,62,57,48,55,34,37,44,43,6,1,8,15,26,29,20,19,174,
    169,160,167,178,181,188,187,150,145,152,159,138,141,132,131,222,217,208,215,194,197,
    204,203,230,225,232,239,250,253,244,243};

uint8_t eps_set_conv_brd_resp[SET_CONV_BRD_RESP_LEN];
uint8_t eps_set_btry_brd_resp[SET_BTRY_BRD_RESP_LEN];
uint8_t eps_set_out_ch_enb_resp[SET_OP_CHNL_RESP_LEN];
uint8_t eps_set_op_chnl_cur_lmt_rsp[SET_OP_CHNL_CUR_LMT];
uint8_t eps_set_mode_resp[SET_EPS_MODE_RESP_LEN];


/**
 * @brief CRC 8 bit calculation
 *
 * @param[in]  message : Destination id of thread
 * @param[in]  length  : Pointer to received data
 *
 * @return calculated CRC value remainder
 *
 */
uint8_t CRC_8_Bit(uint8_t *message,uint8_t length)
{
    uint8_t data,remainder =0;
    uint32_t byte;

    for(byte = 0; byte < length; ++byte)
    {
        data =(message[byte]) ^ (remainder);
        remainder = CRC_Table[data] ^ (message[byte] << 8);
    }

    return (remainder);
}

/**
 * @brief This API provides encoding and decoding of EPS parameters and triggers I2C transaction
 *
 * @param[in]  eps : eps frame infromation
 *
 * @return status of eps_err_sts_e
 * @retval equal to zero -> Success / less than zero -> failure.
 *
 */
static eps_err_sts_e send_eps(eps_send_s *eps)
{
    eps_err_sts_e eps_sts=EPS_INVLD_ARG;
    uint8_t *tx_buff, *rx_buff;
    unsigned char slave_addr=0;
    slave_addr = slave_addr;
    uint8_t rx_buf_len = eps->len_r + 2;
    uint8_t tx_buf_len = eps->len_t + 2;
    eps_err_sts_e err_detct;

    if(!(eps==NULL || eps->tx_buf_ptr==NULL || eps->rx_buf_ptr==NULL))
    {
        tx_buff = (uint8_t*)os_malloc(tx_buf_len);
        rx_buff = (uint8_t*)os_malloc(rx_buf_len);

        tx_buff[0] = eps->command;  //add command bit

        if((tx_buff[0] >= EPS_SET_OP_CHNL_PARM) && (tx_buff[0] <= EPS_GET_ADDR_VAR_OP_BRD))
            slave_addr = EPS_OP_CH_BRD_ADDR;
        else
            slave_addr = EPS_CONV_BRD_ADDR;

        if(tx_buff[0] == EPS_GET_CONV_BRD_FW_VERS)
        	tx_buff[0] = EPS_GET_OP_CHNL_FW_VERS;

        os_memcpy(&tx_buff[1],(eps)->tx_buf_ptr,tx_buf_len-2);

        tx_buff[tx_buf_len-1] = CRC_8_Bit(tx_buff,tx_buf_len-1); //add crc bit

        eps_sts = EPS_COM_FAIL;
#ifdef EPS_SIMU_ENABLE
		if(eps_simu_data_write(tx_buff, tx_buf_len)==0)
		{
			if(eps_simu_data_read(rx_buff, rx_buf_len)==0)
#else
#ifdef JANUS2
		if(io_hal_i2c_transmit(&ioal_hi2c3, slave_addr, tx_buff, tx_buf_len, 200) == HAL_SCS)
#else
		if(io_hal_i2c_transmit(&ioal_hi2c1, slave_addr, tx_buff, tx_buf_len, 200) == HAL_SCS)
#endif
		{
			os_delay(300);
#ifdef JANUS2
			if(io_hal_i2c_receive(&ioal_hi2c3, slave_addr,rx_buff, rx_buf_len, 200) == HAL_SCS)
#else
			if(io_hal_i2c_receive(&ioal_hi2c1, slave_addr,rx_buff, rx_buf_len, 200) == HAL_SCS)
#endif
#endif
                    {
#ifdef EPS_SIMU_ENABLE
                        DEBUG_CPRINT(("\nEPS Tx=>"));
                        for (int i=0;i<tx_buf_len;i++)
                        {
                            DEBUG_CPRINT(("%x ",tx_buff[i]));
                        }
                        DEBUG_CPRINT(("\n"));

                        DEBUG_CPRINT(("\nEPS Rx=>"));
                        for (int i=0;i<rx_buf_len;i++)
                        {
                            DEBUG_CPRINT(("%x ",rx_buff[i]));
                        }
                        DEBUG_CPRINT(("\n"));
#endif
                        if(rx_buff[0] == 0)
                        {
                            if((rx_buff[rx_buf_len-1] != CRC_8_Bit(rx_buff,(rx_buf_len-1))))  // checking CRC
                            {
                                if(eps_crc_cnt[0] < 0xFFFF)
                                    eps_crc_cnt[0]++;

                                eps_sts =  EPS_CRC_FAIL;
                            }
                            else
                            {
                                if(eps_crc_cnt[1] < 0xFFFF)
                                    eps_crc_cnt[1]++;
                                eps_sts = EPS_SUCCESS;
                            }
                            os_memcpy((eps)->rx_buf_ptr,&rx_buff[1],rx_buf_len-2);

                        }
                        else
                        {
                        	eps_sts = EPS_RESP_ERR;
                        }
                    }
            }
        os_free(tx_buff);
        os_free(rx_buff);
		}
#ifdef ERR_HANDL_TEST_HOOK_ENABLE
		if(err_handler_test_hook(ERR_GROUP_EPS, ERR_EPS_COM_FAIL)) err_detct = EPS_COM_FAIL;
		else if(err_handler_test_hook(ERR_GROUP_EPS, ERR_EPS_CRC_FAIL)) err_detct = EPS_CRC_FAIL;
		else if(err_handler_test_hook(ERR_GROUP_EPS, ERR_EPS_RESP_ERR)) err_detct = EPS_RESP_ERR;
		else err_detct = eps_sts;
#else
		err_detct = eps_sts;
#endif
		if(err_detct == EPS_COM_FAIL)
		{
			DEBUG_CPRINT(("EPS Communication Failure\n"));
			if(eps_i2c_reset() == 1)
			{
				err_detected(ERR_GROUP_EPS, ERR_EPS_COM_FAIL);
			}
		}
		else if(err_detct == EPS_CRC_FAIL)
		{
		      err_detected(ERR_GROUP_EPS, ERR_EPS_CRC_FAIL);
		}
		else if(err_detct == EPS_RESP_ERR)
		{
	          err_detected(ERR_GROUP_EPS, ERR_EPS_RESP_ERR);
		}
		else
		{
			err_detct = err_get_fault_status(ERR_GROUP_EPS, ERR_EPS_COM_FAIL);
		    if(err_detct != 0)
			{
				err_cleared(ERR_GROUP_EPS, ERR_EPS_COM_FAIL);
			}

		    err_detct = err_get_fault_status(ERR_GROUP_EPS, ERR_EPS_CRC_FAIL);
		    if(err_detct != 0)
			{
				err_cleared(ERR_GROUP_EPS, ERR_EPS_CRC_FAIL);
			}

		    err_detct = err_get_fault_status(ERR_GROUP_EPS, ERR_EPS_RESP_ERR);
		    if(err_detct != 0)
			{
				err_cleared(ERR_GROUP_EPS, ERR_EPS_RESP_ERR);
			}
		}
    return eps_sts;
}

/**
 * @brief This API transfer received parameter data to EPS module converter board
 *
 */
eps_err_sts_e eps_set_conv_brd_params(eps_set_conv_brd_s *_set_conv_brd, uint8_t *_response)
{
    eps_err_sts_e eps_sts=EPS_INVLD_ARG;
    eps_send_s eps;
    if(_set_conv_brd != NULL )
    {
        if(_set_conv_brd->mppt_enb_cnt == MAX_MPPT_CONV_CNT && _set_conv_brd->conv_op_enb_cnt == MAX_MPPT_CONV_CNT && _set_conv_brd->conv_op_volt_cnt == MAX_MPPT_CONV_CNT )
        {
        eps.len_t 		= sizeof(eps_set_conv_brd_s)-3;
        eps.len_r 		= SET_CONV_BRD_RESP_LEN;
        eps.tx_buf_ptr 	= (uint8_t*)&_set_conv_brd->mem_set;
        eps.rx_buf_ptr  = _response;
        eps.command 	= EPS_SET_CONV_BRD;
        eps_sts				= send_eps(&eps);

        if(eps_sts == EPS_SUCCESS)
        {
        	log_id(LOG_INFO_L3,LOG_EPS,EPS_SET_CONV_BRD_PARAM_SUCCESS);//info log 3 - eps set sc for conv brd param
            if(eps.rx_buf_ptr[0] != 0 )
            {
                //check_recieve_bit(rx_buff,eps);
                eps_sts = EPS_SET_PARAM_ERR;
            }
        }
        }
        else
        {
            eps_sts = EPS_INVLD_ARG;
        }
    }
    else
    {
        eps_sts = EPS_NULL_PTR_ERR;
    }
    return eps_sts;
}

/**
 * @brief This API transfer received data to EPS module rtc
 *
 */
eps_err_sts_e eps_set_rtc_time(eps_set_rtc_tm_s  *set_rtc_tm, uint8_t *_response)
{
	 eps_err_sts_e eps_sts=EPS_INVLD_ARG;
	    eps_send_s eps;
	  #if 0
            DEBUG_CPRINT(("_eps_set_rtc_data->hour = %d;\n",set_rtc_tm->hour));
            DEBUG_CPRINT(("_eps_set_rtc_data->minute = %d;\n", set_rtc_tm->minute));
            DEBUG_CPRINT(("_eps_set_rtc_data->second = %d;\n", set_rtc_tm->second));
            DEBUG_CPRINT(("_eps_set_rtc_data->date = %d;\n", set_rtc_tm->date));
            DEBUG_CPRINT(("_eps_set_rtc_data->month = %d;\n", set_rtc_tm->month));
            DEBUG_CPRINT(("_eps_set_rtc_data->year = %d;\n", set_rtc_tm->year));
#endif

	    if(set_rtc_tm != NULL)
	    {
			eps.len_t 		= sizeof(eps_set_rtc_tm_s);
			eps.len_r 		= SET_RTC_RESV_LEN ;
			eps.tx_buf_ptr 	= (uint8_t*)&set_rtc_tm->hour;
			eps.rx_buf_ptr  = _response;
			eps.command 	= EPS_SET_RTC_DATA;
			eps_sts				= send_eps(&eps);

	    }
	    return eps_sts;
}

/*
 * @brief This API controls the TC and TM for EPS simulator
 */
void eps_tctm_code(obc_pck_data_eps *data)
{
    eps_err_sts_e eps_sts;
    eps_set_conv_brd_s set_conv_brd;
    eps_set_btry_brd_s set_batt_brd;
    eps_set_out_chnl_enb_s set_chnl_en;
    eps_set_out_chnl_crnt_lmt_s set_out_ch_cur_lmt;
    eps_set_mode_s set_mode_par;
    eps_set_obc_com_timeout_s eps_set_obc_com_timeout;

    eps_get_conv_brd_rd_s get_conv_brd_rd;
    eps_get_conv_brd_stng_s get_conv_brd_st;
    eps_get_btry_brd_rd_s get_btry_brd_rd;
    eps_get_btry_brd_stng_s get_btry_brd_st;
    eps_get_out_chnl_sts_s get_out_chnl_params;
    eps_get_stng_mode_resp_s get_mode_params;
    eps_alert_flag_resp_s get_alert_info;
    eps_get_obc_com_timeout_s eps_get_obc_com_timeout;

    eps_get_fw_s get_fw[2];
    eps_get_chnl_cur_rd_s get_cur_chnl_rd;
    eps_get_chnl_cur_stng_s get_cur_chnl_st;
    switch(data->tm_rsp_id)
    {
    case TM_SET_CONV_BOARD_PARM:
    	os_memcpy(&set_conv_brd,data->tx_data,sizeof(eps_set_conv_brd_s));
    	data->rx_data_len = SET_CONV_BRD_RESP_LEN+1;
    	data->rx_data =(uint8_t*)os_malloc(data->rx_data_len);
    	if(data->rx_data != NULL)
    	{
    		eps_sts = eps_set_conv_brd_params(&set_conv_brd,&data->rx_data[1]);
    		os_memcpy(&data->rx_data[0],&eps_sts,1);
    	}
    	break;
    case TM_SET_BATT_BOARD_PARM:
    	os_memcpy(&set_batt_brd,data->tx_data,sizeof(eps_set_btry_brd_s));
    	data->rx_data_len = SET_BTRY_BRD_RESP_LEN+1;
    	data->rx_data =(uint8_t*)os_malloc(data->rx_data_len);
    	if(data->rx_data != NULL)
    	{
    		eps_sts = eps_set_btry_brd_params(&set_batt_brd,&data->rx_data[1]);
    		os_memcpy(&data->rx_data[0],&eps_sts,1);
    	}
    	break;
    case TM_SET_OUT_CHNL_ENB:
    	os_memcpy(&set_chnl_en,data->tx_data,sizeof(eps_set_out_chnl_enb_s));
    	data->rx_data_len = SET_OP_CHNL_RESP_LEN+1;
    	data->rx_data =(uint8_t*)os_malloc(data->rx_data_len);
    	if(data->rx_data != NULL)
    	{
    		eps_sts = eps_set_chnl_state(&set_chnl_en,&data->rx_data[1]);
    		os_memcpy(&data->rx_data[0],&eps_sts,1);
    	}
    	break;
    case TM_SET_OUT_CHNL_CUR_LMT:
    	os_memcpy(&set_out_ch_cur_lmt,data->tx_data,sizeof(eps_set_out_chnl_crnt_lmt_s));
    	data->rx_data_len = SET_OP_CHNL_CUR_LMT+1;
    	data->rx_data =(uint8_t*)os_malloc(data->rx_data_len);
    	if(data->rx_data != NULL)
    	{
    		eps_sts = eps_set_chnl_crnt_lmt(&set_out_ch_cur_lmt,&data->rx_data[1]);
    		os_memcpy(&data->rx_data[0],&eps_sts,1);
    	}
    	break;
    case TM_SET_EPS_MODE_CFG:
    	os_memcpy(&set_mode_par,data->tx_data,sizeof(eps_set_mode_s));
    	data->rx_data_len = SET_EPS_MODE_RESP_LEN+1;
    	data->rx_data =(uint8_t*)os_malloc(data->rx_data_len);
    	if(data->rx_data != NULL)
    	{
    		eps_sts = eps_set_mode_params(&set_mode_par,&data->rx_data[1]);
    		os_memcpy(&data->rx_data[0],&eps_sts,1);
    	}
    	break;
    case TM_SET_EPS_COM_TIMEOUT:
    	os_memcpy(&eps_set_obc_com_timeout,data->tx_data,sizeof(eps_set_obc_com_timeout_s));
    	data->rx_data_len = SET_EPS_COM_TIMEOUT_RESP_LEN+1;
    	data->rx_data = (uint8_t*)os_malloc(data->rx_data_len);
    	if(data->rx_data != NULL)
    	{
    		eps_sts = eps_set_obc_com_time_out(&eps_set_obc_com_timeout,&data->rx_data[1]);
    		os_memcpy(&data->rx_data[0],&eps_sts,1);
    	}
    	break;

    case TM_GET_CONV_BOARD_PARM:
    	if(data->tx_data[0] == 1)
    	{
    		eps_sts = eps_get_conv_brd_read_params(&get_conv_brd_rd);
    		data->rx_data_len=sizeof(eps_get_conv_brd_rd_s)+2;            //extra one is added for status var and the other is for first var
    		data->rx_data = (uint8_t*)os_malloc(data->rx_data_len);
    		os_memcpy(&data->rx_data[2],&get_conv_brd_rd,sizeof(eps_get_conv_brd_rd_s));
    		os_memcpy(&data->rx_data[1],&eps_sts,1);
    		data->rx_data[0] = data->tx_data[0];
    	}
    	else if(data->tx_data[0] == 0)
    	{
    		eps_sts = eps_get_conv_brd_set_params(&get_conv_brd_st);
    		data->rx_data_len=sizeof(eps_get_conv_brd_stng_s)+2;
    		data->rx_data = (uint8_t*)os_malloc(data->rx_data_len);
    		os_memcpy(&data->rx_data[2],&get_conv_brd_st,sizeof(eps_get_conv_brd_stng_s));
    		os_memcpy(&data->rx_data[1],&eps_sts,1);
    		data->rx_data[0] = data->tx_data[0];
    	}
    	else
    	{
    		DEBUG_CPRINT(("Invalid convertor board ID\n"));
    		log_id(LOG_ERROR, LOG_EPS,INVALID_CONVERTOR_BOARD_ID);
    	}
    	break;
    case TM_GET_BATT_BOARD_PARM:
    	if(data->tx_data[0] == 1)
    	{
    		eps_sts = eps_get_btry_brd_read_params(&get_btry_brd_rd);
    		data->rx_data_len=sizeof(eps_get_btry_brd_rd_s)+2;
    		data->rx_data = (uint8_t*)os_malloc(data->rx_data_len);
    		os_memcpy(&data->rx_data[2],&get_btry_brd_rd,sizeof(eps_get_btry_brd_rd_s));
    		os_memcpy(&data->rx_data[1],&eps_sts,1);
    		data->rx_data[0] = data->tx_data[0];
    	}
    	else if(data->tx_data[0] == 0)
    	{
    		eps_sts = eps_get_btry_brd_set_params(&get_btry_brd_st);
    		data->rx_data_len=sizeof(eps_get_btry_brd_stng_s)+2;
    		data->rx_data = (uint8_t*)os_malloc(data->rx_data_len);
    		os_memcpy(&data->rx_data[2],&get_btry_brd_st,sizeof(eps_get_btry_brd_stng_s));
    		os_memcpy(&data->rx_data[1],&eps_sts,1);
    		data->rx_data[0] = data->tx_data[0];
    	}
    	else
    	{
    		DEBUG_CPRINT(("Invalid battery board ID\n"));
    		log_id(LOG_ERROR, LOG_EPS,INVALID_BATTERY_BOARD_ID);
    	}
    	break;
    case TM_GET_OUT_CHNL_PARM:
    	if(data->tx_data[0] == 0)
    	{
    		eps_sts = eps_get_chnl_params(&get_out_chnl_params);
    		data->rx_data_len=sizeof(eps_get_out_chnl_sts_s)+2;
    		data->rx_data = (uint8_t*)os_malloc(data->rx_data_len);
    		os_memcpy(&data->rx_data[2],&get_out_chnl_params,sizeof(eps_get_out_chnl_sts_s));
    		os_memcpy(&data->rx_data[1],&eps_sts,1);
    		data->rx_data[0] = data->tx_data[0];
    	}
    	else if(data->tx_data[0] == 1)
    	{
    		eps_sts = eps_get_op_chnl_cur_rd(&get_cur_chnl_rd);
    		data->rx_data_len=sizeof(eps_get_chnl_cur_rd_s)+2;
    		data->rx_data = (uint8_t*)os_malloc(data->rx_data_len);
    		os_memcpy(&data->rx_data[2],&get_cur_chnl_rd,sizeof(eps_get_chnl_cur_rd_s));
    		os_memcpy(&data->rx_data[1],&eps_sts,1);
    		data->rx_data[0] = data->tx_data[0];
    	}
    	else if(data->tx_data[0] == 2)
    	{
    		eps_sts = eps_get_op_chnl_cur_lmt_st(&get_cur_chnl_st);
    		data->rx_data_len=sizeof(eps_get_chnl_cur_stng_s)+2;
    		data->rx_data = (uint8_t*)os_malloc(data->rx_data_len);
    		os_memcpy(&data->rx_data[2],&get_cur_chnl_st,sizeof(eps_get_chnl_cur_stng_s));
    		os_memcpy(&data->rx_data[1],&eps_sts,1);
    		data->rx_data[0] = data->tx_data[0];
    	}
    	else
    	{
    		DEBUG_CPRINT(("Invalid output channel parameter ID\n"));
    		log_id(LOG_ERROR, LOG_EPS,INVALID_OUTPUT_CHANNEL_PARAMETER_ID);
    	}
    	break;
    case TM_GET_EPS_MODE_CFG:
    	eps_sts = eps_get_mode_params(&get_mode_params);
    	data->rx_data_len=sizeof(eps_get_stng_mode_resp_s)+1;
    	data->rx_data = (uint8_t*)os_malloc(data->rx_data_len);
    	os_memcpy(&data->rx_data[1],&get_mode_params,sizeof(eps_get_stng_mode_resp_s));
    	os_memcpy(&data->rx_data[0],&eps_sts,1);
    	break;
    case TM_GET_EPS_ALERT_INFO:
    	eps_sts = eps_get_alert_flag(&get_alert_info);
    	data->rx_data_len=sizeof(eps_alert_flag_resp_s)+1;
    	data->rx_data = (uint8_t*)os_malloc(data->rx_data_len);
    	os_memcpy(&data->rx_data[1],&get_alert_info,sizeof(eps_alert_flag_resp_s));
    	os_memcpy(&data->rx_data[0],&eps_sts,1);
    	break;
    case TM_GET_EPS_COM_TIMEOUT:
    	eps_sts = eps_get_obc_com_time_out(&eps_get_obc_com_timeout);
    	data->rx_data_len=sizeof(eps_get_obc_com_timeout_s)+1;
    	data->rx_data = (uint8_t*)os_malloc(data->rx_data_len);
    	os_memcpy(&data->rx_data[1],&eps_get_obc_com_timeout,sizeof(eps_get_obc_com_timeout_s));
    	os_memcpy(&data->rx_data[0],&eps_sts,1);
    	break;

#ifdef EPS_SIMU_ENABLE
    case TM_SET_EPS_SIM_EXPOSURE_TYPE:
    	data->rx_data_len = 1;
    	data->rx_data =(uint8_t*)os_malloc(data->rx_data_len);
    	eps_sts = eps_set_expo_simu(data->tx_data);
    	os_memcpy(data->rx_data,&eps_sts,1);
    	break;
    case TM_SET_EPS_SIM_CH_CRNT:
    	data->rx_data_len = 1;
    	data->rx_data =(uint8_t*)os_malloc(data->rx_data_len);
    	eps_sts = eps_set_ch_crnt_simu(data->tx_data);
    	os_memcpy(data->rx_data,&eps_sts,1);
    	break;
    case TM_SET_EPS_SIM_BTRY_VOLT:
    	data->rx_data_len = 1;
    	data->rx_data =(uint8_t*)os_malloc(data->rx_data_len);
    	eps_sts = eps_set_btry_volt_simu(data->tx_data);
    	os_memcpy(data->rx_data,&eps_sts,1);
    	break;
    case TM_SET_EPS_SIM_BTRY_TEMP:
    	data->rx_data_len = 1;
    	data->rx_data =(uint8_t*)os_malloc(data->rx_data_len);
    	eps_sts = eps_set_btry_temp_simu(data->tx_data);
    	os_memcpy(data->rx_data,&eps_sts,1);
    	break;
#endif
    case TM_GET_EPS_FW:
    	eps_sts = eps_get_fw_update(get_fw);
    	data->rx_data_len=sizeof(eps_get_fw_s)*2+1;
    	data->rx_data = (uint8_t*)os_malloc(data->rx_data_len);
    	os_memcpy(&data->rx_data[1],get_fw,data->rx_data_len-1);
    	os_memcpy(&data->rx_data[0],&eps_sts,1);
    	break;

    case TM_EPS_GET_CRC:
    	data->rx_data_len = sizeof(eps_crc_cnt)+1;;
    	data->rx_data =(uint8_t*)os_malloc(data->rx_data_len);
    	if(data->rx_data != NULL)
    	{
    		data->rx_data[0]=1;
    		os_memcpy(&data->rx_data[1],eps_crc_cnt,data->rx_data_len-1);
    	}
    	break;
    default:
    	break;

    }
}

/**
 * @brief This API transfer received parameter data to EPS module battery board
 *
 */
eps_err_sts_e eps_set_btry_brd_params(eps_set_btry_brd_s *_set_bat_brd,uint8_t *_response)
{
    eps_err_sts_e eps_sts=EPS_INVLD_ARG;
    eps_send_s eps;
    if(_set_bat_brd != NULL)
    {
        if(_set_bat_brd->temp_lmt_sns_cnt == MAX_BTRY_TMP_SNSR_CNT)
        {
        eps.tx_buf_ptr  = (uint8_t*)&_set_bat_brd->mem_set;
        eps.rx_buf_ptr  = _response;
        eps.len_t 		= sizeof(eps_set_btry_brd_s)-1;
        eps.len_r 		= SET_BTRY_BRD_RESP_LEN;
        eps.command 	= EPS_SET_BTRY_BRD;
        eps_sts				= send_eps(&eps);
        if(eps_sts == EPS_SUCCESS)
        {
        	log_id(LOG_INFO_L3,LOG_EPS,EPS_SET_BTRY_BRD_PARAM_SUCCESS);
            if(eps.rx_buf_ptr[0] != 0 )
            {
                //check_recieve_bit(rx_buff,eps);
                eps_sts = EPS_SET_PARAM_ERR;
            }
        }
        }
        else
        {
            eps_sts = EPS_INVLD_ARG;
        }
    }
    else
    {
        eps_sts = EPS_NULL_PTR_ERR;
    }
    return eps_sts;
}

/**
 * @brief This API transfer EPS channel state value for all individual output channel
 *
 */
eps_err_sts_e eps_set_chnl_state(eps_set_out_chnl_enb_s *_out_ch_en_sts, uint8_t *_response)
{
    eps_err_sts_e eps_sts=EPS_INVLD_ARG;
    eps_send_s eps;
    if(_out_ch_en_sts != NULL )
    {
        eps.rx_buf_ptr  = _response;
        eps.tx_buf_ptr  = (uint8_t*)&_out_ch_en_sts->mem_set;
        eps.len_t 		= sizeof(eps_set_out_chnl_enb_s);
        eps.len_r 		= SET_OP_CHNL_RESP_LEN;
        eps.command 	= EPS_SET_OP_CHNL_PARM;
        eps_sts				= send_eps(&eps);
        if(eps_sts == EPS_SUCCESS)
        {
        	log_id(LOG_INFO_L3,LOG_EPS,EPS_SET_CHNL_STATE_SUCCESS);
            if(eps.rx_buf_ptr[0] != 0 )
            {
                eps_sts = EPS_SET_PARAM_ERR;
            }
        }
    }
    else
    {
        eps_sts = EPS_NULL_PTR_ERR;
    }
    return eps_sts;
}

/**
 * @brief This API transfer received output channel current limits parameter data to EPS module
 *
 */
eps_err_sts_e eps_set_chnl_crnt_lmt(eps_set_out_chnl_crnt_lmt_s  *_out_ch_cur_lmt, uint8_t *_response)
{
    eps_err_sts_e eps_sts=EPS_INVLD_ARG;
    eps_send_s eps;
    if(_out_ch_cur_lmt != NULL )
    {
        if(_out_ch_cur_lmt->chnl_cnt == MAX_VOLT_RAIL_CNT)
        {
        eps.rx_buf_ptr  = _response;
        eps.tx_buf_ptr  = (uint8_t*)&_out_ch_cur_lmt->mem_set;
        eps.len_t 	= sizeof(eps_set_out_chnl_crnt_lmt_s)-1;
        eps.command 	= EPS_SET_OP_CHNL_CUR;
        eps.len_r 	= SET_OP_CHNL_CUR_LMT;
        eps_sts				= send_eps(&eps);
        if(eps_sts == EPS_SUCCESS)
        {

        	log_id(LOG_INFO_L3,LOG_EPS,EPS_SET_CHNL_CURRENT_LIMIT_PARAM_SUCCESS);
            if(eps.rx_buf_ptr[0] != 0 )
            {
                //check_recieve_bit(rx_buff,eps);
                eps_sts = EPS_SET_PARAM_ERR;
            }
        }
        }
        else
        {
            eps_sts = EPS_INVLD_ARG;
        }
    }
    else
    {
        eps_sts = EPS_NULL_PTR_ERR;
    }
    return eps_sts;
}

/**
 * @brief This API transfer EPS mode parameters data
 *
 */
eps_err_sts_e eps_set_mode_params(eps_set_mode_s *_set_mode_params,uint8_t *_response)
{
    eps_err_sts_e eps_sts=EPS_INVLD_ARG;
    eps_send_s eps;
    eps_btry_thrshld_s btry_thrshld;
    if(_set_mode_params != NULL )
    {
        eps.rx_buf_ptr  = _response;
        eps.tx_buf_ptr  = (uint8_t*)&_set_mode_params->mem_set;
        eps.len_t 		= sizeof(eps_set_mode_s);
        eps.command 	= EPS_SET_MODE_PARM;
        eps.len_r 		= SET_EPS_MODE_RESP_LEN;
        eps_sts			= send_eps(&eps);

        if(eps_sts == EPS_SUCCESS)
        {
        	log_id(LOG_INFO_L3,LOG_EPS,EPS_SET_MODE_PARAMS_SUCCESS);
            if(eps.rx_buf_ptr[0] != 0 )
            {
                //check_recieve_bit(rx_buff,eps);
                eps_sts = EPS_SET_PARAM_ERR;
            }
        }
        btry_thrshld.volt[0] = _set_mode_params->crtl_mode_thrld_volt;
        btry_thrshld.volt[1] = _set_mode_params->safe_mode_thrld_volt;
        btry_thrshld.volt[2] = _set_mode_params->nrml_mode_thrld_volt;
        eps_set_btry_thrshld(&btry_thrshld);
    }
    else
    {
        eps_sts = EPS_NULL_PTR_ERR;
    }
    return eps_sts;
}

/**
 * @brief This API transfer EPS obc communication failure timeout parameter
 *
 */
eps_err_sts_e eps_set_obc_com_time_out(eps_set_obc_com_timeout_s *eps_set_obc_com_timeout,uint8_t *_response)
{
    eps_err_sts_e eps_sts=EPS_INVLD_ARG;
    eps_send_s eps;
    if(eps_set_obc_com_timeout != NULL)
    {
        eps.rx_buf_ptr  = _response;
        eps.tx_buf_ptr  = (uint8_t*)&eps_set_obc_com_timeout->obc_com_timeout_sec;
        eps.len_t               = sizeof(eps_set_obc_com_timeout_s);
        eps.command     = EPS_SET_COM_TIMEOUT;
        eps.len_r               = SET_EPS_COM_TIMEOUT_RESP_LEN;
        eps_sts                 = send_eps(&eps);
        if(eps_sts == EPS_SUCCESS)
        {
            log_id(LOG_INFO_L3,LOG_EPS,EPS_SET_OBC_COM_FAIL_RST_TIMEOUT_SUCCESS);
        }
    }
    else
    {
        eps_sts = EPS_NULL_PTR_ERR;
    }
    return eps_sts;
}

/**
 * @brief This API receives latest EPS converter board read parameter
 *
 */
eps_err_sts_e eps_get_conv_brd_read_params(eps_get_conv_brd_rd_s *_get_conv_brd_rd)
{
    eps_err_sts_e eps_sts=EPS_INVLD_ARG;
    eps_send_s eps;

    if(_get_conv_brd_rd != NULL)
    {
        _get_conv_brd_rd->mppt_enb_cnt=MAX_MPPT_CONV_CNT;
        _get_conv_brd_rd->op_conv_enb_cnt=MAX_MPPT_CONV_CNT;
        _get_conv_brd_rd->pv_volt_cnt=MAX_SLR_PNL_CNT;
        _get_conv_brd_rd->pv_cur_cnt=MAX_SLR_PNL_CNT;
        _get_conv_brd_rd->op_conv_volt_cnt=MAX_MPPT_CONV_CNT;
        eps.tx_buf_ptr  =  (uint8_t*)os_malloc(GET_CONV_BRD_LEN);
        os_memset(eps.tx_buf_ptr,0,GET_CONV_BRD_LEN);
        eps.rx_buf_ptr  =  (uint8_t*)&_get_conv_brd_rd->mppt_enb[0];
        eps.len_t 		=  0;
        eps.len_r 		=  sizeof(eps_get_conv_brd_rd_s)-6;
        eps.command 	=  EPS_GET_CONV_BRD_RD;
        eps_sts				=  send_eps(&eps);
        os_free(eps.tx_buf_ptr);
    }
    else
    {
        eps_sts = EPS_NULL_PTR_ERR;
    }
#if 0
    DEBUG_CPRINT(("conv brd resp rd :%d\n",_get_conv_brd_rd->resp));
    for(uint8_t i =0; i<4;i++)
    {
    DEBUG_CPRINT(("conv brd mppt en sts rd :%hhu\n",_get_conv_brd_rd->mppt_enb[i]));
    DEBUG_CPRINT(("conv brd op conv en :%d\n",_get_conv_brd_rd->op_conv_enb_sts[i]));
    DEBUG_CPRINT(("conv brd pv volt rd :%f\n",_get_conv_brd_rd->pv_volt[i]));
    DEBUG_CPRINT(("conv brd pv cur rd :%f\n",_get_conv_brd_rd->pv_cur[i]));
    DEBUG_CPRINT(("conv brd op conv volt rd :%f\n",_get_conv_brd_rd->op_conv_volt[i]));
    }
#endif
    return eps_sts;
}

/**
 * @brief This API receives latest EPS rtc data
 *
 */
eps_err_sts_e eps_get_rtc_time(eps_get_rtc_tm_s *get_rtc_tm)
{
    eps_err_sts_e eps_sts=EPS_INVLD_ARG;
    eps_send_s eps;

    if(get_rtc_tm != NULL)
    {
        eps.tx_buf_ptr  =  (uint8_t*)os_malloc(GET_RTC_SEN_LEN);
        os_memset(eps.tx_buf_ptr,0, GET_RTC_SEN_LEN);
        eps.rx_buf_ptr  =  (uint8_t*)&get_rtc_tm->hour;
        eps.len_t 		=  0;
        eps.len_r 		=  sizeof(eps_get_rtc_tm_s)-1;
        eps.command 	=  EPS_GET_RTC_DATA;
        eps_sts				=  send_eps(&eps);
        os_free(eps.tx_buf_ptr);
#if 0
         DEBUG_CPRINT(("_eps_get_rtc_data->hour = %d;\n",get_rtc_tm->hour));
         DEBUG_CPRINT(("_eps_get_rtc_data->minute = %d;\n", get_rtc_tm->minute));
         DEBUG_CPRINT(("_eps_get_rtc_data->second = %d;\n", get_rtc_tm->second));
         DEBUG_CPRINT(("_eps_get_rtc_data->date = %d;\n", get_rtc_tm->date));
         DEBUG_CPRINT(("_eps_get_rtc_data->month = %d;\n", get_rtc_tm->month));
         DEBUG_CPRINT(("_eps_get_rtc_data->year = %d;\n", get_rtc_tm->year));
#endif
    }
    else
    {
        eps_sts = EPS_NULL_PTR_ERR;
    }

        return eps_sts;
}

/**
 * @brief This API receives latest EPS converter board parameter set parameter
 *
 */
eps_err_sts_e eps_get_conv_brd_set_params(eps_get_conv_brd_stng_s *_get_conv_brd_st)
{
    eps_err_sts_e eps_sts=EPS_INVLD_ARG;
    eps_send_s eps;

    if(_get_conv_brd_st != NULL)
    {
        _get_conv_brd_st->op_conv_volt_cnt=MAX_MPPT_CONV_CNT;
        eps.tx_buf_ptr  =  (uint8_t*)os_malloc(GET_CONV_BRD_LEN);
        os_memset(eps.tx_buf_ptr,0,GET_CONV_BRD_LEN);
        eps.rx_buf_ptr  =  (uint8_t*)&_get_conv_brd_st->op_conv_volt[0];
        eps.len_t               =  0;
        eps.len_r               =  sizeof(eps_get_conv_brd_stng_s)-2;
        eps.command     =  EPS_GET_CONV_BRD_ST;
        eps_sts                         =  send_eps(&eps);
        os_free(eps.tx_buf_ptr);
        
    }
    else
    {
        eps_sts = EPS_NULL_PTR_ERR;
    }
    return eps_sts;
}

/**
 * @brief This API receives latest EPS battery board read parameter
 *
 */
eps_err_sts_e eps_get_btry_brd_read_params(eps_get_btry_brd_rd_s *_get_batt_brd_rd)
{
    eps_err_sts_e eps_sts=EPS_INVLD_ARG;
    eps_send_s eps;

    if(_get_batt_brd_rd != NULL)
    {
        _get_batt_brd_rd->btry_volt_cnt=MAX_VOLT_THRSH_CNT;
        _get_batt_brd_rd->btry_temp_cnt=MAX_BTRY_TMP_SNSR_CNT;
        eps.tx_buf_ptr  = (uint8_t*)os_malloc(GET_BTRY_BRD_LEN);
        os_memset(eps.tx_buf_ptr,0,GET_BTRY_BRD_LEN);

        eps.rx_buf_ptr  = (uint8_t*)&_get_batt_brd_rd->tot_btry_volt;
        eps.len_t 		= 0;
        eps.len_r 		= sizeof(eps_get_btry_brd_rd_s)-3;
        eps.command 	= EPS_GET_BTRY_BRD_RD;
        eps_sts				= send_eps(&eps);
        os_free(eps.tx_buf_ptr);
    }
    else
    {
        eps_sts = EPS_NULL_PTR_ERR;
    }
    return eps_sts;
}

/**
 * @brief This API receives latest EPS battery board set parameter
 *
 */
eps_err_sts_e eps_get_btry_brd_set_params(eps_get_btry_brd_stng_s *_get_batt_brd_st)
{
    eps_err_sts_e eps_sts=EPS_INVLD_ARG;
    eps_send_s eps;

    if(_get_batt_brd_st != NULL)
    {
        _get_batt_brd_st->btry_temp_sns_cnt=MAX_BTRY_TMP_SNSR_CNT;
        eps.tx_buf_ptr  = (uint8_t*)os_malloc(GET_BTRY_BRD_LEN);
        os_memset(eps.tx_buf_ptr,0,GET_BTRY_BRD_LEN);

        eps.rx_buf_ptr  = (uint8_t*)&_get_batt_brd_st->cur_lmt_chrg;
        eps.len_t               = 0;
        eps.len_r               = sizeof(eps_get_btry_brd_stng_s)-2;
        eps.command     = EPS_GET_BTRY_BRD_ST;
        eps_sts                         = send_eps(&eps);
        os_free(eps.tx_buf_ptr);
    }
    else
    {
        eps_sts = EPS_NULL_PTR_ERR;
    }
    return eps_sts;
}

/**
 * @brief This API receives latest EPS output channel status
 *
 */
eps_err_sts_e eps_get_chnl_params(eps_get_out_chnl_sts_s *_out_chnl_rd)
{
    eps_err_sts_e eps_sts=EPS_INVLD_ARG;
    eps_send_s eps;
    if(_out_chnl_rd != NULL)
    {
        eps.tx_buf_ptr =(uint8_t*)os_malloc(GET_OP_CHNL_PARM_LEN);
        os_memset(eps.tx_buf_ptr,0,GET_OP_CHNL_PARM_LEN);
        eps.rx_buf_ptr  = (uint8_t*)&_out_chnl_rd->chnl1_8;
        eps.len_t 		= 0;
        eps.len_r 		= sizeof(eps_get_out_chnl_sts_s)-1;
        eps.command 	= EPS_GET_OP_CHNL_PARM;
        eps_sts			= send_eps(&eps);

        os_free(eps.tx_buf_ptr);
    }
    else
    {
        eps_sts = EPS_NULL_PTR_ERR;
    }
    return eps_sts;
}

/**
 * @brief This API receives latest EPS output channel current limit read parameter
 *
 */
eps_err_sts_e eps_get_op_chnl_cur_rd(eps_get_chnl_cur_rd_s *_out_chnl_cur_rd)
{
    eps_err_sts_e eps_sts=EPS_INVLD_ARG;
    eps_send_s eps;
    if(_out_chnl_cur_rd != NULL)
    {
        _out_chnl_cur_rd->volt_rail_cnt=MAX_VOLT_RAIL_CNT;
        eps.tx_buf_ptr =(uint8_t*)os_malloc(GET_OP_CHNL_PARM_LEN);
        os_memset(eps.tx_buf_ptr,0,GET_OP_CHNL_PARM_LEN);

        eps.rx_buf_ptr  = (uint8_t*)&_out_chnl_cur_rd->volt_rail[0];
        eps.len_t               = 0;
        eps.len_r               = sizeof(eps_get_chnl_cur_rd_s)-2;
        eps.command     = EPS_GET_OP_CHNL_CUR_RD;
        eps_sts                 = send_eps(&eps);

        os_free(eps.tx_buf_ptr);
    }
    else
    {
        eps_sts = EPS_NULL_PTR_ERR;
    }
    return eps_sts;
}

/**
 * @brief This API receives latest EPS output channel current limit set parameter
 *
 */
eps_err_sts_e eps_get_op_chnl_cur_lmt_st(eps_get_chnl_cur_stng_s *_out_chnl_cur_lmt_st)
{
    eps_err_sts_e eps_sts=EPS_INVLD_ARG;
    eps_send_s eps;
    if(_out_chnl_cur_lmt_st != NULL)
    {
        _out_chnl_cur_lmt_st->volt_rail_cnt=MAX_VOLT_RAIL_CNT;
        eps.tx_buf_ptr =(uint8_t*)os_malloc(GET_OP_CHNL_PARM_LEN);
        os_memset(eps.tx_buf_ptr,0,GET_OP_CHNL_PARM_LEN);

        eps.rx_buf_ptr  = (uint8_t*)&_out_chnl_cur_lmt_st->volt_rail[0];
        eps.len_t               = 0;
        eps.len_r               = sizeof(eps_get_chnl_cur_stng_s)-2;
        eps.command     = EPS_GET_OP_CHNL_CUR_LMT_SET;
        eps_sts                 = send_eps(&eps);

        os_free(eps.tx_buf_ptr);
    }
    else
    {
        eps_sts = EPS_NULL_PTR_ERR;
    }
    return eps_sts;
}

/**
 * @brief This API receives previously stored EPS mode parameter value.
 *
 */
eps_err_sts_e eps_get_mode_params(eps_get_stng_mode_resp_s *_get_mode_par)
{
    eps_err_sts_e eps_sts=EPS_INVLD_ARG;
    eps_send_s eps;
    if(_get_mode_par != NULL)
    {
        eps.tx_buf_ptr  =(uint8_t*)os_malloc(GET_EPS_MODE_LEN);
        os_memset(eps.tx_buf_ptr,0,GET_EPS_MODE_LEN);

        eps.rx_buf_ptr  = (uint8_t*)&_get_mode_par->nrml_mode_thrld_volt;
        eps.len_t 		= 0;
        eps.len_r 		= sizeof(eps_get_stng_mode_resp_s)-1;
        eps.command 	= EPS_GET_MODE_PARM;
        eps_sts				= send_eps(&eps);
        os_free(eps.tx_buf_ptr);
    }
    else
    {
        eps_sts = EPS_NULL_PTR_ERR;
    }
    return eps_sts;
}

/**
 * @brief This API receives alert flag values if threshold reaches maximum or minimum limit in EPS
 *
 */
eps_err_sts_e eps_get_alert_flag(eps_alert_flag_resp_s *_alert_flag)
{
    eps_err_sts_e eps_sts=EPS_INVLD_ARG;
    eps_send_s eps;
    if(_alert_flag != NULL)
    {
        eps.tx_buf_ptr  = (uint8_t*)os_malloc(EPS_ALERT_FLAG_LEN);
        os_memset(eps.tx_buf_ptr,0,EPS_ALERT_FLAG_LEN);


        eps.rx_buf_ptr  = (uint8_t*)&_alert_flag->mode;
        eps.len_t 		= 0;
        eps.len_r 		= sizeof(eps_alert_flag_resp_s)-1;
        eps.command 	= EPS_GET_ALRT_FLAG;
        eps_sts			= send_eps(&eps);
        os_free(eps.tx_buf_ptr);
    }
    else
    {
        eps_sts = EPS_NULL_PTR_ERR;
    }
    return eps_sts;
}

/**
 * @brief This API receives OBC communication failure reset timeout in EPS
 *
 */
eps_err_sts_e eps_get_obc_com_time_out(eps_get_obc_com_timeout_s *eps_get_obc_com_timeout)
{
	eps_err_sts_e eps_sts=EPS_INVLD_ARG;
	eps_send_s eps;
	if(eps_get_obc_com_timeout != NULL)
	{
		eps.tx_buf_ptr  = (uint8_t*)os_malloc(GET_EPS_COM_TIMEOUT_TX_LEN);
		os_memset(eps.tx_buf_ptr,0,GET_EPS_COM_TIMEOUT_TX_LEN);

		eps.rx_buf_ptr  = (uint8_t*)&eps_get_obc_com_timeout->obc_com_timeout_sec_byte1;
		eps.len_t               = 0;
		eps.len_r               = sizeof(eps_get_obc_com_timeout_s)-1;
		eps.command     = EPS_GET_COM_TIMEOUT;
		eps_sts                 = send_eps(&eps);
		os_free(eps.tx_buf_ptr);
	}
	else
	{
		eps_sts = EPS_NULL_PTR_ERR;
	}
	return eps_sts;
}

/**
 * @brief This API receives latest EPS firmware version
 *
 */
eps_err_sts_e eps_get_fw_update(eps_get_fw_s *_get_fw)
{
    eps_err_sts_e eps_sts=EPS_INVLD_ARG;
    eps_send_s eps;
    if(_get_fw != NULL)
    {
        eps.tx_buf_ptr  = (uint8_t*)os_malloc(EPS_FW_LEN);
        os_memset(eps.tx_buf_ptr,0,EPS_FW_LEN);

        eps.rx_buf_ptr  = (uint8_t*)&_get_fw[0].fw_mjr_vers;
        eps.len_t               = 0;
        eps.len_r               = sizeof(eps_get_fw_s)-1;
        eps.command     = EPS_GET_OP_CHNL_FW_VERS;
        eps_sts                 = send_eps(&eps);

        eps.rx_buf_ptr  = (uint8_t*)&_get_fw[1].fw_mjr_vers;
		eps.len_t               = 0;
		eps.len_r               = sizeof(eps_get_fw_s)-1;
		eps.command     = EPS_GET_CONV_BRD_FW_VERS;
		eps_sts                 = send_eps(&eps);
        os_free(eps.tx_buf_ptr);
    }
    else
    {
        eps_sts = EPS_NULL_PTR_ERR;
    }
    return eps_sts;
}

/**
 * @brief This API receives EPS battery board parameter, extract and store latest necessary
 * 		 parameters from entire set of parameters
 *
 */
eps_err_sts_e eps_get_btry_brd_params_read(eps_get_btry_brd_tmr_s *_eps_get_btry_board_par_tmr)
{
    eps_err_sts_e _eps_err_sts = EPS_SUCCESS;

    eps_get_btry_brd_rd_s get_batt_brd_rd;
    _eps_err_sts=eps_get_btry_brd_read_params(&get_batt_brd_rd);
    if(_eps_err_sts == EPS_SUCCESS || _eps_err_sts == EPS_CRC_FAIL)
    {
    	log_id(LOG_INFO_L3,LOG_EPS,EPS_GET_BTRY_BOARD_PARAM_READ_SUCCESS);
    	_eps_get_btry_board_par_tmr->btry_temp_cnt = get_batt_brd_rd.btry_temp_cnt;
    	_eps_get_btry_board_par_tmr->btry_volt_cnt = get_batt_brd_rd.btry_volt_cnt;
    _eps_get_btry_board_par_tmr->totl_vol = get_batt_brd_rd.tot_btry_volt;
    os_memcpy(&_eps_get_btry_board_par_tmr->vol_ch,&get_batt_brd_rd.btry_volt,sizeof(float)*MAX_VOLT_THRSH_CNT);
    _eps_get_btry_board_par_tmr->totl_crnt=get_batt_brd_rd.btry_cur;
    os_memcpy(&_eps_get_btry_board_par_tmr->tempr,&get_batt_brd_rd.btry_temp,MAX_BTRY_TMP_SNSR_CNT);
    _eps_get_btry_board_par_tmr->btry_chrg_sts=get_batt_brd_rd.btry_flg;
    }
    return _eps_err_sts;
}

/**
 * @brief This API receives EPS converter board parameter, extract and store latest necessary
 * 		 parameters from entire set of parameters
 *
 */
eps_err_sts_e eps_get_conv_brd_params_read(eps_get_conv_brd_tmr_s *_get_conv_brd_params_tmr)
{
    eps_err_sts_e _eps_err_sts =EPS_SUCCESS ;

    eps_get_conv_brd_rd_s get_conv_brd_rd;
    _eps_err_sts = eps_get_conv_brd_read_params(&get_conv_brd_rd);
    if(_eps_err_sts == EPS_SUCCESS || _eps_err_sts == EPS_CRC_FAIL)
    {
    	log_id(LOG_INFO_L3,LOG_EPS,EPS_GET_CONV_BOARD_PARAM_READ_SUCCESS);
    	_get_conv_brd_params_tmr->op_conv_volt_cnt = get_conv_brd_rd.op_conv_volt_cnt;
    	_get_conv_brd_params_tmr->pv_volt_cnt = get_conv_brd_rd.pv_volt_cnt;
    	_get_conv_brd_params_tmr->pv_cur_cnt = get_conv_brd_rd.pv_cur_cnt;
    os_memcpy(&_get_conv_brd_params_tmr->op_volt_conv_read,&get_conv_brd_rd.op_conv_volt,MAX_MPPT_CONV_CNT*sizeof(float));
	os_memcpy(&_get_conv_brd_params_tmr->pv_cur,&get_conv_brd_rd.pv_cur,MAX_SLR_PNL_CNT*sizeof(float));
	os_memcpy(&_get_conv_brd_params_tmr->pv_volt,&get_conv_brd_rd.pv_volt,MAX_SLR_PNL_CNT*sizeof(float));
    }
    return _eps_err_sts;
}

/**
 * @brief This API receives EPS output channel parameters, extract and store latest necessary
 * 		 parameters from entire set of parameters
 *
 */
eps_err_sts_e eps_get_chnl_params_read(eps_get_chnl_par_tmr_s *_eps_get_chnl_par)
{
    eps_err_sts_e _eps_err_sts = EPS_SUCCESS;

    eps_get_chnl_cur_rd_s out_chnl_cur_rd;
    _eps_err_sts=eps_get_op_chnl_cur_rd(&out_chnl_cur_rd);
    if(_eps_err_sts == EPS_SUCCESS || _eps_err_sts == EPS_CRC_FAIL)
    {
    	log_id(LOG_INFO_L3,LOG_EPS,EPS_GET_CHNL_BOARD_PARAM_READ_SUCCESS);
    	_eps_get_chnl_par->volt_rail_cnt = out_chnl_cur_rd.volt_rail_cnt;
    os_memcpy(&_eps_get_chnl_par->rd_crnt_val,&out_chnl_cur_rd.volt_rail,MAX_VOLT_RAIL_CNT*sizeof(float));
    }
    return _eps_err_sts;
}

/**
 * @brief This API receives EPS alert flag values and store latest necessary values
 *
 */
eps_err_sts_e eps_get_alert_flag_read(eps_alert_flag_tmr_s *_eps_alert_flag_tmr)
{
    eps_err_sts_e _eps_err_sts;
    //eps_alert_flag_s *alert_flag;
    eps_alert_flag_resp_s *alert_flag;
    uint32_t value = 0;			
    uint8_t tmp_cnt = 0;

    alert_flag = os_malloc(sizeof(eps_alert_flag_resp_s));
    _eps_err_sts = eps_get_alert_flag(alert_flag);

    if(_eps_err_sts == EPS_SUCCESS || _eps_err_sts == EPS_CRC_FAIL)
    {
#ifndef DRISHTI_EN
        while(tmp_cnt < 16)
        {
#else
        while(tmp_cnt < 11)
        {
#endif
            if(tmp_cnt < 8)
            {
                if(EPS_GET_CHNL(alert_flag->chnl1_5_ovr_cur_flg,tmp_cnt))
                    value |= 1 << tmp_cnt;
            }
#ifndef DRISHTI_EN
            else if(tmp_cnt > 7 || tmp_cnt <=15) 
#else
            else if(tmp_cnt > 7 || tmp_cnt <=10) 
#endif
            {
                if(EPS_GET_CHNL(alert_flag->chnl6_11_ovr_cur_flg,tmp_cnt%8))
                    value |= 1 << tmp_cnt;
            }
            else
            {
            }
            tmp_cnt++;
        }
        value  = value<<3;
        value |= alert_flag->mode & 0x07;

       if(EPS_GET_CHNL(alert_flag->btry_chrg_ovrcur_flg,0))
            value |= 0x80000;

       if(EPS_GET_CHNL(alert_flag->btry_dischrg_ovrcur_flg,0))
            value |= 0x100000;

		if(EPS_GET_CHNL(alert_flag->btry_volt_blw_10_7v,0))
			value |= 0x200000;
#ifndef DRISHTI_EN
		value |= (alert_flag->chnl_num) << 22;
#else
		value |= (alert_flag->chnl_num) << 17;
#endif
		_eps_alert_flag_tmr->hour = alert_flag->hour;
		_eps_alert_flag_tmr->min = alert_flag->min;
		_eps_alert_flag_tmr->sec = alert_flag->sec;
	}
	_eps_alert_flag_tmr->value=value;
	os_free(alert_flag);
	return _eps_err_sts;
}
#if 0
/**
 * @brief This API receives variable data from given address value
 *
 */
eps_err_sts_e eps_get_variable_data(eps_slv_type slv_type,eps_set_var_addr_s *_addr, eps_get_var_data_s *_var)
{
    eps_err_sts_e eps_sts=EPS_INVLD_ARG;
    eps_send_s eps;
    if(_addr != NULL && _var != NULL)
    {
        eps.tx_buf_ptr  = (uint8_t*)_addr;
        eps.rx_buf_ptr  = (uint8_t*)_var;
        eps.len_t 		= sizeof(eps_set_var_addr_s);
        eps.len_r 		= sizeof(eps_get_var_data_s);
        if(slv_type == conv_brd)
            eps.command 	= EPS_GET_ADDR_VAR_CONV_BRD;
        else
            eps.command 	= EPS_GET_ADDR_VAR_OP_BRD;

        eps_sts				= send_eps(&eps);
    }
    return eps_sts;
}
#endif
/**
 * @brief This API controls on off state of output channel
 *
 */
eps_err_sts_e eps_en_chnl(uint8_t ch_no,ch_state  state)
{
    eps_err_sts_e eps_sts=EPS_INVLD_ARG;
    eps_set_out_chnl_enb_s  new_val;
    eps_get_out_chnl_sts_s crnt_val;

    uint8_t response[21];

    if( ch_no< MAX_EPS_OUT_CH_CNT)
    {
#ifndef DRISHTI_EN
        if(ch_no != HW_X_BAND)
        {
#endif
            eps_sts = eps_get_chnl_params(&crnt_val);
            if(eps_sts == EPS_SUCCESS)
            {
                if((((EPS_GET_CHNL(crnt_val.chnl1_8,ch_no)) != state) && ch_no < 8) || (((EPS_GET_CHNL(crnt_val.chnl9_12,ch_no%8)) != state) && ch_no >= 8))
                {
                    new_val.chnl1_8 = crnt_val.chnl1_8;
                    new_val.chnl9_12 = crnt_val.chnl9_12;
                    //copy current channel values to update only new specific channel
                    if(state == 1)
                    {
                        if(ch_no < 8)
                        {
                            EPS_CHNL_ON(new_val.chnl1_8,ch_no);
                        }
#ifndef DRISHTI_EN
                        else if(ch_no >= 8 || ch_no < 12)
#else
                        else if(ch_no >= 8 || ch_no < 11)
#endif
                        {
                            EPS_CHNL_ON(new_val.chnl9_12,ch_no%8);
                        }
                        else
                        {
                        }
                    }
                    else if(state == 0)
                    {
                        if(ch_no < 8)
                        {
                            EPS_CHNL_OFF(new_val.chnl1_8,ch_no);
                        }
#ifndef DRISHTI_EN
                        else if(ch_no >= 8 || ch_no < 12)
#else
                        else if(ch_no >= 8 || ch_no < 11)
#endif
                        {
                            EPS_CHNL_OFF(new_val.chnl9_12,ch_no%8);
                        }
                        else
                        {
                        }
                    }
                    else
                    {
                    }
                    //                    new_val.state[ch_no] = state;
                    new_val.mem_set = TEMP_MEM;

                    eps_sts = eps_set_chnl_state(&new_val,response);

                    if(eps_sts==EPS_SET_PARAM_ERR)
                    {
                        if(response[ch_no + 2] == 1)
                            eps_sts=EPS_SUCCESS;
                    }
                }
            }
#ifndef DRISHTI_EN
        }
        else
        {
            return EPS_SET_PARAM_ERR;
        }
#endif

    }
    return eps_sts;
}

/**
 * @brief This API receives total battery voltage from battery board parameters
 *
 */
eps_err_sts_e eps_get_totl_btry_volt(float *btry_volt)
{
    eps_err_sts_e eps_sts=EPS_INVLD_ARG;
    eps_get_btry_brd_rd_s get_btry_brd_val;

    eps_sts=eps_get_btry_brd_read_params(&get_btry_brd_val);

    if(eps_sts==EPS_SUCCESS)
   *btry_volt = get_btry_brd_val.tot_btry_volt;
    return eps_sts;
}

/**
 * @brief This function handle the I2C reset while error occur
 * in I2C
 */
uint8_t eps_i2c_reset()
{
	uint32_t i2c_err_code;
	uint8_t reset_sts = 1;
#ifdef JANUS2
	i2c_err_code = io_hal_i2c_get_err(&ioal_hi2c3);
#else
        i2c_err_code = io_hal_i2c_get_err(&ioal_hi2c1);
#endif
	//Check if acknowledgment failure(0x4) is occur otherwise reset
	//the i2c
	if(i2c_err_code != 0x4)
	{
#ifdef JANUS2
		//De-Initialize I2C
		io_hal_i2c_deinit(&ioal_hi2c3);
		//Initialize I2C
		io_hal_i2c_init(&ioal_hi2c3,IOAL_INST_I2C3);
#else
                //De-Initialize I2C
                io_hal_i2c_deinit(&ioal_hi2c1);
                //Initialize I2C
                io_hal_i2c_init(&ioal_hi2c1,IOAL_INST_I2C1);
#endif

		reset_sts = 0;
	}
	else
	{
		reset_sts = 1;
	}

	return reset_sts;
}

#ifdef EPS_SIMU_ENABLE
/**
 * @brief This API set the exposure
 */
eps_err_sts_e eps_set_expo_simu(uint8_t* data)
{
    eps_err_sts_e eps_sts=EPS_INVLD_ARG;
   uint8_t response[3];
    eps_send_s eps;
    if(data!= NULL)
    {
    	if(data[0] == EXPOSURE_LUT_SIZE)
    	{
    		eps.rx_buf_ptr  = response;
    		eps.tx_buf_ptr  = (uint8_t*)data;
    		eps.len_t               = sizeof(eps_sim_expo_s);
    		eps.command     = EPS_SIM_EXPOSURE_TYPE;
    		eps.len_r               = 1;
    		eps_sts                 = send_eps(&eps);
    	}
    	else
		{
			eps_sts = EPS_INVLD_ARG;
		}

    }
    return eps_sts;
}

/*!
 * @brief This API set the channel surrent
 */
eps_err_sts_e eps_set_ch_crnt_simu(uint8_t* data)
{
    eps_err_sts_e eps_sts=EPS_INVLD_ARG;
    uint8_t response[3];
    eps_send_s eps;
    if(data!= NULL)
    {
    	if(data[0] == MAX_VOLT_RAIL_CNT)
    	{
    		eps.rx_buf_ptr  = response;
    		eps.tx_buf_ptr  = (uint8_t*)data;
    		eps.len_t               = sizeof(eps_sim_ch_crnt_s);
    		eps.command     = EPS_SET_CH_CRNT_SIMU;
    		eps.len_r               = 1;
    		eps_sts                 = send_eps(&eps);
    	}
    	else
    	{
    		eps_sts =  EPS_INVLD_ARG;
    	}
    }
    return eps_sts;
}

/**
 * @brief This API set the battery voltage
 */
eps_err_sts_e eps_set_btry_volt_simu(uint8_t* data)
{
    eps_err_sts_e eps_sts=EPS_INVLD_ARG;
    uint8_t response[3];
    eps_send_s eps;
    if(data!= NULL)
    {
        eps.rx_buf_ptr  = response;
        eps.tx_buf_ptr  = (uint8_t*)data;
        eps.len_t               = sizeof(eps_sim_btry_volt_s);
        eps.command     = EPS_SET_BTRY_VOLT_SIMU;
        eps.len_r               = 1;
        eps_sts                 = send_eps(&eps);
    }
    return eps_sts;
}

/**
 * This API set the battery temperature
 */
eps_err_sts_e eps_set_btry_temp_simu(uint8_t* data)
{
    eps_err_sts_e eps_sts=EPS_INVLD_ARG;
    uint8_t response[3];
    eps_send_s eps;
    if(data!= NULL)
    {
        eps.rx_buf_ptr  = response;
        eps.tx_buf_ptr  = (uint8_t*)data;
        eps.len_t               = sizeof(eps_sim_btry_temp_s);
        eps.command     = EPS_SET_BTRY_TEMP_SIMU;
        eps.len_r               = 1;
        eps_sts                 = send_eps(&eps);
    }
    return eps_sts;
}
#endif
