
/**
 * @file xband_main_fsm_hdlr.c
 *
 * @brief This file has the X-Band driver FSM implemenation and the relevant functions
 *
 * @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 "sm_api.h"
#include "xband_ipc.h"
#include "xband_main.h"
#include "exo_common.h"
#include "xband_xlink_api.h"
#include "xband_xlink_ss.h"
#include "logger.h"
#include "exo_tctm_ipc.h"


uint16_t PLACE_IN_EXT_RAM_MEM xband_tc_seq_no = 0;
uint8_t PLACE_IN_EXT_RAM_MEM xband_radio_id = 0;
extern uint32 PLACE_IN_EXT_RAM_MEM lastProductKey[4] ;		//!< last valid product key to save computing power

/** Declaration of X-Driver FSM function pointer */
typedef uint8_t (*XBAND_SM_HDLR)(uint16_t msg_id, void *payload);

/** Definition of X-BAND Driver FSM function pointer */
XBAND_SM_HDLR xband_fsm_hdlr[XBAND_MAX_NUM_STATE] = {\
    &xband_init_state_hdlr,\
    &xband_boot_state_hdlr,\
    &xband_dfu_state_hdlr,\
    &xband_cfg_state_hdlr,\
    &xband_calib_state_hdlr,\
    &xband_sleep_idle_state_hdlr,\
    &xband_active_state_hdlr,\
    &xband_safe_mode_state_hdlr,\
    &xband_error_state_hdlr,\
    &xband_bypass_state_hdlr\
};

/**
 * @brief This function handle xband initialization state
 */
uint8_t xband_init_state_hdlr(uint16_t msg_id, void *payload)
{
    uint8_t state = XBAND_INIT_STATE;

    DEBUG_CPRINT(("received response for XBAND_RESET : %d \n", msg_id));
    log_id_with_one_arg(LOG_INFO_L1,LOG_COMMS,RECEIVED_RESPONSE_FOR_XBAND_RESET__u16_,msg_id);
    switch (msg_id)
    {
        case OBC_XBAND_INIT_REQ:
            {
                state = XBAND_ACTIVE_STATE;
                xband_send_ipc(XBAND_OBC_INIT_RSP,OBC_MAIN);
            }
            break;

        default:
            state = XBAND_SAFE_MODE_STATE;
            break;
    }

    return state;
}

/**
 * @brief This function handle the xband boot state
 */
uint8_t xband_boot_state_hdlr(uint16_t msg_id, void *payload)
{
    uint8_t state = XBAND_BOOT_STATE;
    int8_t status = XBAND_IPC_OK;

    DEBUG_CPRINT(("received response for XBAND_BOOT : %d \n", msg_id));
    log_id_with_one_arg(LOG_INFO_L1,LOG_COMMS,RECEIVED_RESPONSE_FOR_XBAND_BOOT__u16_,msg_id);
    switch (msg_id)
    {
        case XBAND_BOOT_DONE:
            DEBUG_CPRINT(("In BOOT_DONE state \n "));
            log_id(LOG_INFO_L1,LOG_COMMS,IN__BOOT_DONE_STATE);
            state = XBAND_DFU_STATE;
            //TODO:Firmware update API to be added
            //xband_main_trans_msg.Msg_id = XBAND_INTRNL_FRMWR_UPDT_REQ;
            DEBUG_CPRINT(("In BOOT_DONE state, status of internal dfu request is %d \n ",status));
            log_id_with_one_arg(LOG_INFO_L1,LOG_COMMS,IN_BOOT_DONE_STATE__STATUS_OF_INTERNAL_DFU_REQUEST_IS__s8_,status);
            break;

        case XBAND_BOOT_FAIL:
            DEBUG_CPRINT(("BOOT_FAIL event \n"));
            log_id(LOG_ERROR,LOG_COMMS,BOOT_FAIL_EVENT);
            state = XBAND_ERROR_STATE;
            break;

        default:
            state = XBAND_SAFE_MODE_STATE ;
            break;
    }
    return state;
}

/**
 * @brief This function handles xband DFU states
 */
uint8_t xband_dfu_state_hdlr(uint16_t msg_id, void *payload)
{
    uint8_t state = XBAND_DFU_STATE;

    DEBUG_CPRINT(("received response for XBAND_DFU : %d \n", msg_id));
    log_id_with_one_arg(LOG_INFO_L1,LOG_COMMS,RECEIVED_RESPONSE_FOR_XBAND_DFU__u16_,msg_id);
    switch (msg_id)
    {
        case XBAND_DFU_DONE:
            state = XBAND_CFG_STATE;
            break;

        case XBAND_DFU_FAIL:
            DEBUG_CPRINT(("DFU_FAIL event \n"));
            log_id(LOG_ERROR,LOG_COMMS,DFU_FAIL_EVENT);
            state = XBAND_ERROR_STATE ;
            break;

        default:
            state = XBAND_SAFE_MODE_STATE ;
            break;
    }
    return state;
}

/**
 * @brief This function handle xband configuration states
 */
uint8_t xband_cfg_state_hdlr(uint16_t msg_id, void *payload)
{
    uint8_t state = XBAND_CFG_STATE;

    switch (msg_id)
    {
        case 0:
            break;

        default:
            state = XBAND_SAFE_MODE_STATE ;
            break;
    }
    return state;
}

/**
 * @brief This function handle xband calibration state
 */
uint8_t xband_calib_state_hdlr(uint16_t msg_id, void *payload)
{
    uint8_t state = XBAND_CALIB_STATE;

    DEBUG_CPRINT(("received response for XBAND_CLAIB : %d \n", msg_id));
    log_id_with_one_arg(LOG_INFO_L1,LOG_COMMS,RECEIVED_RESPONSE_FOR_XBAND_CLAIB__u16_,msg_id);
    switch (msg_id)
    {
        case XBAND_CALIB_DONE:
            DEBUG_CPRINT(("In CALIB_DONE state \n "));
            log_id(LOG_INFO_L1,LOG_COMMS,IN__CALIB_DONE_STATE);
            state = XBAND_SLEEP_IDLE_STATE;
            break;

        case XBAND_CALIB_FAIL:
            DEBUG_CPRINT(("CALIB_FAIL event \n"));
            log_id(LOG_ERROR,LOG_COMMS,CALIB_FAIL_EVENT);
            state = XBAND_ERROR_STATE ;
            break;

        default:
            state = XBAND_SAFE_MODE_STATE ;
            break;
    }
    return state;
}

/**
 * @brief This API handle the xband idle state
 */
uint8_t xband_sleep_idle_state_hdlr(uint16_t msg_id, void *payload)
{
    uint8_t state = XBAND_SLEEP_IDLE_STATE;

    DEBUG_CPRINT(("received response for XBAND_SLEEP : %d \n", msg_id));
    log_id_with_one_arg(LOG_INFO_L1,LOG_COMMS,RECEIVED_RESPONSE_FOR_XBAND_SLEEP__u16_,msg_id);
    switch (msg_id)
    {
        case XBAND_SLEEP_DONE:
            DEBUG_CPRINT(("In SLEEP_IDLE_DONE state \n "));
            log_id(LOG_INFO_L1,LOG_COMMS,IN__SLEEP_IDLE_DONE_STATE);
            state = XBAND_ACTIVE_STATE;
            break;

        case XBAND_SLEEP_FAIL:
            DEBUG_CPRINT(("SLEEP_IDLE_FAIL event \n"));
            log_id(LOG_ERROR,LOG_COMMS,SLEEP_IDLE_FAIL_EVENT);
            state = XBAND_ERROR_STATE ;
            break;

        default:
            state = XBAND_SAFE_MODE_STATE ;
            break;
    }
    return state;
}

/**
 * @brief This API handle the xband active states
 */
uint8_t xband_active_state_hdlr(uint16_t msg_id, void *payload)
{
    uint8_t state = XBAND_ACTIVE_STATE;

    DEBUG_CPRINT(("received response for XBAND_ACTIVE_STATE : %d \n", msg_id));
    log_id_with_one_arg(LOG_INFO_L1,LOG_COMMS,RECEIVED_RESPONSE_FOR_XBAND_ACTIVE_STATE__u16_,msg_id);
    switch (msg_id)
    {
        case OBC_XBAND_DEINIT_REQ:
            {
                state = XBAND_INIT_STATE;
                xband_send_ipc(XBAND_OBC_DEINIT_RSP,OBC_MAIN);
            }
            break;

        default:
            state = XBAND_SAFE_MODE_STATE ;
            break;
    }
    return state;
}

/**
 * @brief This functions handle the xband safe mode state
 */
uint8_t xband_safe_mode_state_hdlr(uint16_t msg_id, void *payload)
{
    uint8_t state = XBAND_SAFE_MODE_STATE;
    //int8_t status = XBAND_IPC_OK;
    //xband_main_trans_msg.Msg_id = ADCS_RESET_REQUEST;
    //    DEBUG_CPRINT(("sending internal adcs reset request \n"));
    /*status = xband_send_ipc(&xband_main_trans_msg,\
    event_thread_handler,\
        os_wait_forever);*/
    return state;
}

/**
 * @brief This function handle the xband error state
 */
uint8_t xband_error_state_hdlr(uint16_t msg_id, void *payload)
{
    uint8_t state = XBAND_ERROR_STATE;
    return state;
}

/**
 * @brief This function handling Bypass the xband states
 */
uint8_t xband_bypass_state_hdlr(uint16_t msg_id, void *payload)
{
    uint8_t state = XBAND_BYPASS_STATE;

    uint8_t *tc_tm_data;

    DEBUG_CPRINT(("\nXBAND_BYPASS_State\n"));
    log_id(LOG_INFO_L1,LOG_COMMS,XBAND__BYPASS_STATE);

    switch (msg_id)
    {
        case OBC_XBAND_INIT_REQ:
            {
                /** Nothing to be done */
                xband_send_ipc(XBAND_OBC_INIT_RSP,OBC_MAIN);
            }
            break;

        case OBC_XBAND_DEINIT_REQ:
            {
                /** Nothing to be done */
                xband_send_ipc(XBAND_OBC_DEINIT_RSP,OBC_MAIN);
            }
            break;

        case OBC_XBAND_IPCC_RCV_RSP:
            {
                xband_proc_rcv_data(payload);
            }
            break;

        case TC_XBAND_SET_IDLE_CFG:
            {
                DEBUG_CPRINT(("\n\r TC_XBAND_SET_IDLE_CFG is received "));
                log_id(LOG_INFO_L1,LOG_COMMS,TC_XBAND_SET_IDLE_CFG_IS_RECEIVED);

                tc_tm_data = (uint8*)payload;
                os_memcpy(&xband_tc_seq_no,tc_tm_data,sizeof(uint16));
                os_memcpy(&xband_radio_id,&tc_tm_data[TC_RADIO_MOD_IDX],sizeof(uint8));

                xband_proc_tc(SERVICE_SET | SERVICE_IDLE);

            }
            break;

        case TC_XBAND_SET_RESET:
            {
                DEBUG_CPRINT(("\n\r TC_XBAND_SET_RESET is received "));
                log_id(LOG_INFO_L1,LOG_COMMS,TC_XBAND_SET_RESET_IS_RECEIVED);

                tc_tm_data = (uint8*)payload;
                os_memcpy(&xband_tc_seq_no,tc_tm_data,sizeof(uint16));
                os_memcpy(&xband_radio_id,&tc_tm_data[TC_RADIO_MOD_IDX],sizeof(uint8));

                xband_proc_tc(SERVICE_SET | SERVICE_RESET);
            }
            break;

        case TC_XBAND_SET_START_RF_RCV:
            {
                DEBUG_CPRINT(("\n\r TC_XBAND_SET_START_RF_RCV is received "));
                log_id(LOG_INFO_L1,LOG_COMMS,TC_XBAND_SET_START_RF_RCV_IS_RECEIVED);

                tc_tm_data = (uint8*)payload;
                os_memcpy(&xband_tc_seq_no,tc_tm_data,sizeof(uint16));
                os_memcpy(&xband_radio_id,&tc_tm_data[TC_RADIO_MOD_IDX],sizeof(uint8));

                xband_proc_tc_pld((SERVICE_SET | SERVICE_START_RF_RCV),&tc_tm_data[TC_PLD_IDX]);
            }
            break;

        case TC_XBAND_SET_RF_XMT_DATA:
            {
                DEBUG_CPRINT(("\n\r TC_XBAND_SET_RF_XMT_DATA is received "));
                log_id(LOG_INFO_L1,LOG_COMMS,TC_XBAND_SET_RF_XMT_DATA_IS_RECEIVED);

                tc_tm_data = (uint8*)payload;
                os_memcpy(&xband_tc_seq_no,tc_tm_data,sizeof(uint16));
                os_memcpy(&xband_radio_id,&tc_tm_data[TC_RADIO_MOD_IDX],sizeof(uint8));

                xband_proc_tc_pld((SERVICE_SET | SERVICE_RF_XMT_DATA),&tc_tm_data[TC_PLD_IDX]);
            }
            break;

        case TC_XBAND_SET_DVBS2_CONF:
            {
                DEBUG_CPRINT(("\n\r TC_XBAND_SET_DVBS2_CONF is received "));
                log_id(LOG_INFO_L1,LOG_COMMS,TC_XBAND_SET_DVBS2_CONF_IS_RECEIVED);

                tc_tm_data = (uint8*)payload;
                os_memcpy(&xband_tc_seq_no,tc_tm_data,sizeof(uint16));
                os_memcpy(&xband_radio_id,&tc_tm_data[TC_RADIO_MOD_IDX],sizeof(uint8));

                xband_proc_tc_pld((SERVICE_SET | SERVICE_DVBS2_CONF),&tc_tm_data[TC_PLD_IDX]);
            }
            break;

        case TC_XBAND_SET_IP_ADR_SAVE:
            {
                DEBUG_CPRINT(("\n\r TC_XBAND_SET_IP_ADR_SAVE is received "));
                log_id(LOG_INFO_L1,LOG_COMMS,TC_XBAND_SET_IP_ADR_SAVE_IS_RECEIVED);

                tc_tm_data = (uint8*)payload;
                os_memcpy(&xband_tc_seq_no,tc_tm_data,sizeof(uint16));
                os_memcpy(&xband_radio_id,&tc_tm_data[TC_RADIO_MOD_IDX],sizeof(uint8));

                xband_proc_tc_pld((SERVICE_SET | SERVICE_IP_ADR_SAVE),&tc_tm_data[TC_PLD_IDX]);
            }
            break;

        case TC_XBAND_SET_IP_ADR:
            {
                DEBUG_CPRINT(("\n\r TC_XBAND_SET_IP_ADR is received "));
                log_id(LOG_INFO_L1,LOG_COMMS,TC_XBAND_SET_IP_ADR_IS_RECEIVED);

                tc_tm_data = (uint8*)payload;
                os_memcpy(&xband_tc_seq_no,tc_tm_data,sizeof(uint16));
                os_memcpy(&xband_radio_id,&tc_tm_data[TC_RADIO_MOD_IDX],sizeof(uint8));

                xband_proc_tc_pld((SERVICE_SET | SERVICE_IP_ADR),&tc_tm_data[TC_PLD_IDX]);
            }
            break;

        case TC_XBAND_GET_IP_ADR:
            {
                DEBUG_CPRINT(("\n\r TC_XBAND_GET_IP_ADR is received "));
                log_id(LOG_INFO_L1,LOG_COMMS,TC_XBAND_GET_IP_ADR_IS_RECEIVED);

                tc_tm_data = (uint8*)payload;
                os_memcpy(&xband_tc_seq_no,tc_tm_data,sizeof(uint16));
                os_memcpy(&xband_radio_id,&tc_tm_data[TC_RADIO_MOD_IDX],sizeof(uint8));

                xband_proc_tc(SERVICE_GET | SERVICE_IP_ADR);
            }
            break;

        case TC_XBAND_GET_FLAGS_CONF:
            {
                DEBUG_CPRINT(("\n\r TC_XBAND_GET_FLAGS_CONF is received "));
                log_id(LOG_INFO_L1,LOG_COMMS,TC_XBAND_GET_FLAGS_CONF_IS_RECEIVED);

                tc_tm_data = (uint8*)payload;
                os_memcpy(&xband_tc_seq_no,tc_tm_data,sizeof(uint16));
                os_memcpy(&xband_radio_id,&tc_tm_data[TC_RADIO_MOD_IDX],sizeof(uint8));

                xband_proc_tc(SERVICE_GET | SERVICE_FLAGS_CONF);
            }
            break;

        case TC_XBAND_SET_FLAGS_CONF:
            {
                DEBUG_CPRINT(("\n\r TC_XBAND_SET_FLAGS_CONF is received "));
                log_id(LOG_INFO_L1,LOG_COMMS,TC_XBAND_SET_FLAGS_CONF_IS_RECEIVED);

                tc_tm_data = (uint8*)payload;
                os_memcpy(&xband_tc_seq_no,tc_tm_data,sizeof(uint16));
                os_memcpy(&xband_radio_id,&tc_tm_data[TC_RADIO_MOD_IDX],sizeof(uint8));

                xband_proc_tc(SERVICE_SET | SERVICE_FLAGS_CONF);
            }
            break;

        case TC_XBAND_SET_VERSION:
            {
                DEBUG_CPRINT(("\n\r TC_XBAND_SET_VERSION is received "));
                log_id(LOG_INFO_L1,LOG_COMMS,TC_XBAND_SET_VERSION_IS_RECEIVED);

                tc_tm_data = (uint8*)payload;
                os_memcpy(&xband_tc_seq_no,tc_tm_data,sizeof(uint16));
                os_memcpy(&xband_radio_id,&tc_tm_data[TC_RADIO_MOD_IDX],sizeof(uint8));

                xband_proc_tc_pld((SERVICE_SET | SERVICE_VERSION),&tc_tm_data[TC_PLD_IDX]);
            }
            break;

        case TC_XBAND_GET_VERSION:
            {
                DEBUG_CPRINT(("\n\r TC_XBAND_GET_VERSION is received "));
                log_id(LOG_INFO_L1,LOG_COMMS,TC_XBAND_GET_VERSION_IS_RECEIVED);

                tc_tm_data = (uint8*)payload;
                os_memcpy(&xband_tc_seq_no,tc_tm_data,sizeof(uint16));
                os_memcpy(&xband_radio_id,&tc_tm_data[TC_RADIO_MOD_IDX],sizeof(uint8));

                xband_proc_tc(SERVICE_GET | SERVICE_VERSION);
            }
            break;

        case TC_XBAND_SET_DEVICE_CONF:
            {
                DEBUG_CPRINT(("\n\r TC_XBAND_SET_DEVICE_CONF is received "));
                log_id(LOG_INFO_L1,LOG_COMMS,TC_XBAND_SET_DEVICE_CONF_IS_RECEIVED);

                tc_tm_data = (uint8*)payload;
                os_memcpy(&xband_tc_seq_no,tc_tm_data,sizeof(uint16));
                os_memcpy(&xband_radio_id,&tc_tm_data[TC_RADIO_MOD_IDX],sizeof(uint8));

                xband_proc_tc_pld((SERVICE_SET | SERVICE_DEVICE_CONF),&tc_tm_data[TC_PLD_IDX]);
            }
            break;

        case TC_XBAND_GET_DEVICE_CONF:
            {
                DEBUG_CPRINT(("\n\r TC_XBAND_GET_DEVICE_CONF is received "));
                log_id(LOG_INFO_L1,LOG_COMMS,TC_XBAND_GET_DEVICE_CONF_IS_RECEIVED);

                tc_tm_data = (uint8*)payload;
                os_memcpy(&xband_tc_seq_no,tc_tm_data,sizeof(uint16));
                os_memcpy(&xband_radio_id,&tc_tm_data[TC_RADIO_MOD_IDX],sizeof(uint8));

                xband_proc_tc(SERVICE_GET | SERVICE_DEVICE_CONF);
            }
            break;

        case TC_XBAND_GET_FEATURE_SELECT:
            {
                DEBUG_CPRINT(("\n\r TC_XBAND_GET_FEATURE_SELECT is received "));
                log_id(LOG_INFO_L1,LOG_COMMS,TC_XBAND_GET_FEATURE_SELECT_IS_RECEIVED);

                tc_tm_data = (uint8*)payload;
                os_memcpy(&xband_tc_seq_no,tc_tm_data,sizeof(uint16));
                os_memcpy(&xband_radio_id,&tc_tm_data[TC_RADIO_MOD_IDX],sizeof(uint8));

                xband_proc_tc(SERVICE_GET | SERVICE_FEATURE_SELECT);
            }
            break;

        case TC_XBAND_GET_HOUSE_KEEP:
            {
                DEBUG_CPRINT(("\n\r TC_XBAND_GET_HOUSE_KEEP is received "));
                log_id(LOG_INFO_L1,LOG_COMMS,TC_XBAND_GET_HOUSE_KEEP_IS_RECEIVED);

                tc_tm_data = (uint8*)payload;
                os_memcpy(&xband_tc_seq_no,tc_tm_data,sizeof(uint16));
                os_memcpy(&xband_radio_id,&tc_tm_data[TC_RADIO_MOD_IDX],sizeof(uint8));

                xband_proc_tc(SERVICE_GET | SERVICE_HOUSE_KEEP);
            }
            break;

        case TC_XBAND_GET_XPA_INF:
            {
                DEBUG_CPRINT(("\n\r TC_XBAND_GET_XPA_INF is received "));
                log_id(LOG_INFO_L1,LOG_COMMS,TC_XBAND_GET_XPA_INF_IS_RECEIVED);

                tc_tm_data = (uint8*)payload;
                os_memcpy(&xband_tc_seq_no,tc_tm_data,sizeof(uint16));
                os_memcpy(&xband_radio_id,&tc_tm_data[TC_RADIO_MOD_IDX],sizeof(uint8));

                xband_proc_tc(SERVICE_GET | SERVICE_XPA_INF);
            }
            break;

        case TC_XBAND_SET_PROD_KEY:
            {
                DEBUG_CPRINT(("\n\r TC_XBAND_SET_PROD_KEY is received "));
                log_id(LOG_INFO_L1,LOG_COMMS,TC_XBAND_SET_PROD_KEY_IS_RECEIVED);

                tc_tm_data = (uint8*)payload;
                os_memcpy(&xband_tc_seq_no,tc_tm_data,sizeof(uint16));
                os_memcpy(lastProductKey,&tc_tm_data[TM_PLD_IDX],sizeof(lastProductKey));

                xband_tc_tm_set_rsp_hdlr(TM_XBAND_SET_PROD_KEY,0);
            }
            break;

        default:
            state = XBAND_SAFE_MODE_STATE ;
            break;
    }
    return state;
}

/**
 * @brief This API handle the comms xband finite states machine
 */
uint8_t xband_fsm_hdlr_fn(uint8_t state,uint16_t msg_id, void *payload)
{
    return(xband_fsm_hdlr[state](msg_id,payload));
}
