/*
 * Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD
 * All rights reserved.
 *
 * Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use
 * exclusively with CVA's microcontroller products. This file can be freely
 * distributed within development tools that are supporting such microcontroller
 * products.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
 * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
 * CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
 * OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 */

#ifndef _LIN_INTERFACE_H_
#define _LIN_INTERFACE_H_

/*! \brief his file exports Lin interface defnitions
 *
 */

/*******************************************************************************
 * the includes
 ******************************************************************************/

#include <stdint.h>
#include <stdbool.h>
#include "lin_type.h"
#include "lin_cfg.h"

/*! \addtogroup lin_interface
 *  @{
 */

#ifdef __cplusplus
extern "C" {
#endif

/*******************************************************************************
 * the defines
 ******************************************************************************/

/*******************************************************************************
 * the typedefs
 ******************************************************************************/

typedef bool (*pLinIf_SendFrameFunctionPtr)(uint8_t channelIdx, const Lin_PduType *pduInfoPtr);
typedef uint8_t (*pLinIf_CalculateChecksumFunctionPtr)(Lin_CheckSumType checkSumType, uint8_t pid, const uint8_t *sduPtr, uint8_t dataLen);
typedef void (*pLinIf_SendWakeUpSignalFunctionPtr)(uint8_t channelIdx);
typedef bool (*pLinIf_GetWakeupSignalFunctionPtr)(uint8_t channelIdx);
typedef void (*pLinIf_ResetFunctionPtr)(uint8_t channelIdx);
typedef void (*pLinIf_InitFunctionPtr)(uint8_t channelIdx, Lin_NodeType nodeType);
typedef void (*pLinIf_DeInitFunctionPtr)(uint8_t channelIdx);

typedef struct
{
    pLinIf_InitFunctionPtr pLinIf_InitFunction;
    pLinIf_DeInitFunctionPtr pLinIf_DeInitFunction;
    pLinIf_ResetFunctionPtr  pLinIf_ResetFunction;
    pLinIf_SendFrameFunctionPtr pLinIf_SendFrameFunction;
    pLinIf_SendWakeUpSignalFunctionPtr pLinIf_SendWakeUpSignalFunction;
    pLinIf_GetWakeupSignalFunctionPtr  pLinIf_GetWakeupSignalFunction;
    pLinIf_CalculateChecksumFunctionPtr pLinIf_CalculateChecksumFunction;
} LinIf_CallBackFuncListType;

typedef struct
{
    Lin_PduType        pdu; /* local pdu */
    Lin_OpStatusType   opStatusInfo;
    Lin_FrameDataType *upperLevelFrameDataPtr; /* Upper pdu pointer */
    uint32_t           rxTimeOutCnt;
    uint32_t           txTimeOutCnt;
    bool               sleepReqIndication;

    LinIf_CallBackFuncListType *pLinIf_CallBackFuncListPtr;
} LinIf_StateType;

typedef struct
{
    LinIf_StateType pduState[LINCFG_CH_NUM];

    bool                              callBackInstalled;
    const LinIf_CallBackFuncListType *pLinIf_CallBackFuncListPtr;
}LinIf_CtrlInfoType;

/*******************************************************************************
 * the globals
 ******************************************************************************/

/*******************************************************************************
 * the function prototypes
 ******************************************************************************/

/*! \brief Install the call back function
 *
 * This function execute to initialize the lin interface
 *
 * \param[in] callbackList: the call back interface from lin driver in lin interface layer
 * \return: void
 */
extern void LinIf_CallbackInit(const LinIf_CallBackFuncListType *callbackList);

    /*! \brief Initialize the Lin Interface
 *
 * This function execute to initialize the lin interface
 *
 * \param[in] channelIdx: which physical channel is used
 * \param[in] nodeType: the current node type
 * \return: void
 */
extern void LinIf_Init(uint8_t channelIdx, Lin_NodeType nodeType);

/*! \brief DeInitialize the Lin Interface
 *
 * This function execute to initialize the lin interface
 *
 * \param[in] channelIdx: which physical channel is used
 * \return: void
 */
extern void LinIf_DeInit(uint8_t channelIdx);

/*! \brief Convert frame id to pid
 *
 * This function execute to convert the frame id to protected id
 *
 * \param[in] frameId: Frame id, this includes the low 6bit
 * \return: the result of convert pid
 */
extern uint8_t          LinIf_ConvertFrameIdToPid(uint8_t frameId);

/*! \brief Convert pid to frame id
 *
 * This function execute to convert pid to frame id
 *
 * \param[in] pid: protected id
 * \return: the result of convert frame id
 */
extern uint8_t          LinIf_ConvertPidToFrameId(uint8_t pid);

/*! \brief Request transmit the frame
 *
 * This function execute to request transmit the frame, the function is only used by master node
 *
 * \param[in] channelIdx: which physical channel is used
 * \param[in] frameInfoPtr: the pointer of frame
 * \return: true: request transmit successfully
 *          false: request transmit failed
 */
extern bool             LinIf_ReqTransmit(uint8_t channelIdx, const Lin_FrameInfoType *frameInfoPtr);

/*! \brief Get the transfer operated status
 *
 * This function execute to get the current transfer status
 *
 * \param[in] channelIdx: which physical channel is used
 * \return: the status of current transfer operation
 */
extern Lin_OpStatusType LinIf_GetTransferOperateStatus(uint8_t channelIdx);

/*! \brief Send wake-up signal
 *
 * This function execute to send wake-up signal
 *
 * \param[in] channelIdx: which physical channel is used
 * \return: void
 */
extern void             LinIf_SendWakeUpSignal(uint8_t channelIdx);

/*! \brief Get the signal of wake-up
 *
 * This function execute to get the signal of wake-up
 *
 * \param[in] channelIdx: which physical channel of lin to be selected
 * \return: true: wake-up signal is valid
 *          false: wake-up signal is invalid
 */
extern bool LinIf_GetWakeupSignal(uint8_t channelIdx);

/*! \brief Set the sleep request indication flag
 *
 * This function execute to sleep request indication, Indication Upper layer that go to sleep cmd is doing
 *
 * \param[in] channelIdx: which physical channel is used
 * \return: void
 */
extern void             LinIf_SetSleepRequestIndication(uint8_t channelIdx);

/*! \brief Clear the sleep request
 *
 * This function execute to clear the sleep reqeust indication
 *
 * \param[in] channelIdx: which physical channel is used
 * \return: void
 */
extern void             LinIf_ClearSleepRequestIndication(uint8_t channelIdx);

/*! \brief Get the sleep request indication
 *
 * This function execute to get the sleep request indication after enter into prepare sleep mode
 *
 * \param[in] channelIdx: which physical channel is used
 * \return: bool
 */
extern bool             LinIf_GetSleepRequestIndication(uint8_t channelIdx);

/*! \brief Process the current transfer operation timeout
 *
 * This function execute to calculate the current transfer is timeout or not
 *
 * \param[in] channelIdx: which physical channel is used
 * \return: void
 */
extern void             LinIf_MainFunction(uint8_t channelIdx);

/*! \brief The call-back function when received valid header
 *
 * This function execute to process the pdu attribute by received pid, this function is only used by slave node, this is called by isr
 *
 * \param[in] uint8_t channelIdx: which physical channel is used
 * \param[in] pid: the received pid
 * \param[in] pduInfoPtr: the local pdu pointer
 * \return: true: the current received pid is valid and the frame control is not the no-action type
 *          false; the pid is invalid or not supported or the frame control is the no-action type
 */
extern bool LinIf_HeaderIndication(uint8_t channelIdx, uint8_t pid, Lin_PduType **pduInfoPtr);

/*! \brief Received indication
 *
 * This function execute to indicate the upper layer that one new received frame is done, this is called by isr
 *
 * \param[in] channelIdx: which physical channel is used
 * \return: void
 */
extern void LinIf_RxIndication(uint8_t channelIdx);

/*! \brief Transfer confirmed
 *
 * This function execute to tell upper layer that one transfer is done successfully,, this is called by isr
 *
 * \param[in] channelIdx: which physical channel is used
 * \return: void
 */
extern void LinIf_TxConfirmation(uint8_t channelIdx);

/*! \brief Transfer or receive indicate
 *
 * This function execute to indicate that one data is received or one data is transmitted, then to clear the timeout counter,, this is called by isr
 *
 * \param[in] channelIdx: which physical channel is used
 * \return: void
 */
extern void LinIf_TRxIndication(uint8_t channelIdx);

/*! \brief Indicate error information
 *
 * This function execute to report the error information, this is called by isr
 *
 * \param[in] channelIdx: which physical channel is used
 * \param[in] errStatus: the current error information
 * \return: void
 */
extern void LinIf_ErrorIndication(uint8_t channelIdx, Lin_OpStatusType errStatus);

/*! \brief Process the frame data length
 *
 * This function execute to process the link data length by the event-trigger frame id, this is called by isr
 *
 * \param[in] channelIdx: which physical channel is used
 * \param[in] pid: the first data in the response of event trigger frame, the event frame is link to one unconditional frame, the first data in payload is pid
 * \param[in] pDataLen: the pointer of data length
 * \param[in] nodeType: node type
 * \return: void
 */
extern void LinIf_EventFrameDataLenIndication(uint8_t channelIdx, uint8_t pid, uint8_t *pDataLen, Lin_NodeType nodeType);

#ifdef __cplusplus
}
#endif /* extern "C" */

/*! @}*/

#endif /* _LIN_INTERFACE_H_ */
