#ifndef CAN_LIB_H_
#define CAN_LIB_H_

/* #define Platform_16Bit
 #define Platform_32Bit*/
#ifdef Platform_16Bit
    #define canlib_uint8_t  unsigned char
    #define canlib_uint16_t unsigned int
    #define canlib_uint32_t unsigned long

#else

    #define canlib_uint8_t  unsigned char
    #define canlib_uint16_t unsigned short
    #define canlib_uint32_t unsigned int
    #define canlib_uint64_t unsigned long long
#endif

#define CAN_RX_MSG_Block (( canlib_uint8_t )(24U / 4u))
#define CAN_TX_MSG_Block (( canlib_uint8_t )(32U / 4u))

typedef void (*MSG_CKB_ON_RECEIVE)(canlib_uint8_t CopyData []);
typedef void (*MSG_CKB_ON_PROCESS)(canlib_uint8_t CopyData []);
typedef void (*MSG_CKB_ON_LOST)(canlib_uint8_t CopyData []);
typedef void (*pfnMsgBufferSet)(canlib_uint8_t CopyData []);
typedef void (*pfnMsgSuccess)(void);

typedef enum
{
    CAN_ERR_OK,
    CAN_ERR_ParaInit,
    CAN_ERR_OUTRANGE,
} CAN_FUNC_ERR_t;

typedef struct
{
    canlib_uint8_t     INIT_Aarry [ 8u ];
    canlib_uint8_t     TIMEOUT_Array [ 8u ];
    canlib_uint8_t     MASK_Array [ 8u ];
    canlib_uint32_t    MSG_TIMEOUT_VAL;
    canlib_uint32_t    MSG_Identifier;
    MSG_CKB_ON_RECEIVE Msg_ReceiveCBK;
    MSG_CKB_ON_PROCESS Msg_ProcessCBK;
    MSG_CKB_ON_LOST    Msg_LOSTCBK;
} st_CANMsgAttribute;

typedef struct
{
    canlib_uint32_t u32MsgID;
    canlib_uint32_t u32MsgCycle;
    canlib_uint32_t u32MsgCycleOffset;
    canlib_uint32_t u32InitSendCnt;
    canlib_uint8_t  u8MsgSTD_EXT;
    canlib_uint8_t  u8MsgPro;
    canlib_uint8_t  u8MsgDLC;
    canlib_uint8_t  u8TXMsgType;
    pfnMsgBufferSet MsgBufferSet;
    pfnMsgSuccess   MsgSuccess;
} st_CAN_SendAttribute;

typedef struct
{
    canlib_uint32_t MsgID;
    canlib_uint8_t  MsgStd;
    canlib_uint8_t  MsgRTR;
    canlib_uint8_t  MsgDLC;
    canlib_uint8_t  MsgPro;
    canlib_uint8_t  Msg [ 8 ];
} st_CAN_Msg;

typedef canlib_uint8_t (*HAL_CAN_Send)(st_CAN_Msg *Msg);

extern void           CAN_RX_SetEnable(canlib_uint8_t RX_enable);
extern canlib_uint8_t CAN_RX_ReadEnableSts(void);

extern void           CAN_TX_SetEnable(canlib_uint8_t TX_enable);
extern canlib_uint8_t CAN_TX_ReadEnableSts(void);

extern void           Can_Write_Fun(canlib_uint32_t u32CbkCycle);
extern CAN_FUNC_ERR_t Can_Msg_Tx_Overwrite(canlib_uint32_t u32TxMsgIdx, canlib_uint16_t u16TxMSgDIMcounter, canlib_uint32_t u32TxMsgCycle);
extern CAN_FUNC_ERR_t Can_TX_BuffInit(canlib_uint8_t *MemSpace, const st_CAN_SendAttribute *Array, canlib_uint16_t length, HAL_CAN_Send pfunc);
extern void           Can_Msg_TX_SUCCESS(canlib_uint32_t u32TxMsgIdx);
extern CAN_FUNC_ERR_t Can_Msg_TX_FastInitCycle(canlib_uint32_t u32TxMsgIdx, canlib_uint32_t CurTimerCnt);

extern void           Can_RX_BuffInit(canlib_uint8_t *memSpace, const st_CANMsgAttribute *array, canlib_uint16_t length);
extern void           CanMSg_XMS_Analysis(canlib_uint16_t CbkCycle);
extern void           Co_Can_Buff_Set(canlib_uint16_t MsgID, canlib_uint8_t m_DLC, canlib_uint8_t Msg []);
extern canlib_uint8_t CAN_MSG_Status(canlib_uint16_t MsgID);
extern canlib_uint8_t CAN_MSG_Read(canlib_uint16_t MsgIdx, canlib_uint8_t BuffIdx);
extern void           Can_RX_ResetAllTimer(void);
extern void           Can_RX_ResetTimer(canlib_uint16_t idx);

extern canlib_uint32_t Read_CAN_RX_Version(void);
extern canlib_uint32_t Read_CAN_TX_Version(void);

#endif
