////////////////////////////////////////////////////////////////////////////////
/// @file     hal_can.h
/// @author   AE TEAM
/// @brief    THIS FILE CONTAINS ALL THE FUNCTIONS PROTOTYPES FOR THE CAN
///           FIRMWARE LIBRARY.
////////////////////////////////////////////////////////////////////////////////
/// @attention
///
/// THE EXISTING FIRMWARE IS ONLY FOR REFERENCE, WHICH IS DESIGNED TO PROVIDE
/// CUSTOMERS WITH CODING INFORMATION ABOUT THEIR PRODUCTS SO THEY CAN SAVE
/// TIME. THEREFORE, MINDMOTION SHALL NOT BE LIABLE FOR ANY DIRECT, INDIRECT OR
/// CONSEQUENTIAL DAMAGES ABOUT ANY CLAIMS ARISING OUT OF THE CONTENT OF SUCH
/// HARDWARE AND/OR THE USE OF THE CODING INFORMATION CONTAINED HEREIN IN
/// CONNECTION WITH PRODUCTS MADE BY CUSTOMERS.
///
/// <H2><CENTER>&COPY; COPYRIGHT MINDMOTION </CENTER></H2>
////////////////////////////////////////////////////////////////////////////////

// Define to prevent recursive inclusion
#ifndef __HAL_CAN_H
#define __HAL_CAN_H

// Files includes
#include "types.h"
#include "reg_can.h"

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup MM32_Hardware_Abstract_Layer
/// @{

////////////////////////////////////////////////////////////////////////////////
/// @defgroup CAN_HAL
/// @brief CAN HAL modules
/// @{

////////////////////////////////////////////////////////////////////////////////
/// @defgroup CAN_Exported_Types
/// @{



////////////////////////////////////////////////////////////////////////////////
/// @brief CAN_Initialization
////////////////////////////////////////////////////////////////////////////////
typedef enum {
    CANINITFAILED = 0x00000000,  ///< CAN initialization failed
    CANINITOK     = 0x00000001   ///< CAN initialization ok
} emCAN_INIT_Typedef;

////////////////////////////////////////////////////////////////////////////////
/// @brief CAN_sleep_constants
////////////////////////////////////////////////////////////////////////////////
typedef enum {
    CANSLEEPFAILED = 0x00000000,  ///< CAN did not enter the sleep mode
    CANSLEEPOK     = 0x00000001   ///< CAN entered the sleep mode
} emCAN_SLEEP_conts_Typedef;

////////////////////////////////////////////////////////////////////////////////
/// @brief CAN_wake_up_constants
////////////////////////////////////////////////////////////////////////////////
typedef enum {
    CANWAKEUPFAILED = 0x00000000,  ///< CAN did not leave the sleep mode
    CANWAKEUPOK     = 0x00000001   ///< CAN leaved the sleep mode
} emCAN_WAKE_conts_Typedef;

////////////////////////////////////////////////////////////////////////////////
/// @brief CAN_Mode
////////////////////////////////////////////////////////////////////////////////
typedef enum {
    CAN_BASICMode         = 0x00000000,
    CAN_PELIMode          = 0x00000080,
    CAN_WorkMode          = 0x00000080,
    CAN_ResetMode         = 0x00000001,
    CAN_ListenOnlyMode    = 0x00000002,
    CAN_SeftTestMode      = 0x00000004,
    CAN_FilterMode_Singal = 0x00000008,
    CAN_FilterMode_Double = 0x000000f7,
    CAN_SleepMode         = 0x00000010
} emCAN_CAN_Mode_Typedef;

////////////////////////////////////////////////////////////////////////////////
/// @brief BASIC_CAN_interrupt
////////////////////////////////////////////////////////////////////////////////
typedef enum {
    CAN_IT_RIE = CAN_CR_RIE,                                                    ///< Overflow interrupt enable
    CAN_IT_TIE = CAN_CR_TIE,                                                    ///< Transmit interrupt enable
    CAN_IT_EIE = CAN_CR_EIE,                                                    ///< Error interrupt enable
    CAN_IT_OIE = CAN_CR_OIE                                                     ///< Receive interrupt enable
} emCAN_BASIC_IntEn_Typedef;

////////////////////////////////////////////////////////////////////////////////
/// @brief PELI_CAN_interrupt
////////////////////////////////////////////////////////////////////////////////
typedef enum {
    CAN_IT_RI  = CAN_IR_RI,                                                     ///< Overflow interrupt enable
    CAN_IT_TI  = CAN_IR_TI,                                                     ///< Transmit interrupt enable
    CAN_IT_EI  = CAN_IR_EI,                                                     ///< Error interrupt enable
    CAN_IT_DOI = CAN_IR_DOI,                                                    ///< Receive interrupt enable
    CAN_IT_WUI = 0x00001010,                                                    ///< Receive interrupt enable
    CAN_IT_EPI = CAN_IR_EPI,                                                    ///< Receive interrupt enable
    CAN_IT_ALI = CAN_IR_ALI,                                                    ///< Receive interrupt enable
    CAN_IT_BEI = CAN_IR_BEI,                                                    ///< Receive interrupt enable
    CAN_IT_ALL = 0xFFFF                                                         ///< Receive interrupt enable

} emCAN_PELI_IntEn_Typedef;

////////////////////////////////////////////////////////////////////////////////
/// @brief CAN_Status
////////////////////////////////////////////////////////////////////////////////
typedef enum {
    CAN_STATUS_RBS = CAN_SR_RBS,
    CAN_STATUS_DOS = CAN_SR_DOS,
    CAN_STATUS_TBS = CAN_SR_TBS,
    CAN_STATUS_TCS = CAN_SR_TCS,
    CAN_STATUS_RS  = CAN_SR_RS,
    CAN_STATUS_TS  = CAN_SR_TS,
    CAN_STATUS_ES  = CAN_SR_ES,
    CAN_STATUS_BS  = CAN_SR_BS
} emCAN_Status_Typedef;

////////////////////////////////////////////////////////////////////////////////
/// @brief CAN_Command_register
////////////////////////////////////////////////////////////////////////////////
typedef enum {
    CAN_TR  = CAN_CMR_TR,  ///< Transmission request
    CAN_AT  = CAN_CMR_AT,
    CAN_RRB = CAN_CMR_RRB,
    CAN_CDO = CAN_CMR_CDO
} emCAN_Command_Typedef;

////////////////////////////////////////////////////////////////////////////////
/// @brief  CAN_Peli transmit frame definition
////////////////////////////////////////////////////////////////////////////////
typedef enum {
    DataFrame   = 0,  ///< Data Frame
    RemoteFrame = !DataFrame
} TransFrame;

////////////////////////////////////////////////////////////////////////////////
/// @brief  CAN_Basic init structure definition
////////////////////////////////////////////////////////////////////////////////
typedef struct {
    u8              SJW;
    u8              BRP;
    FlagStatus      SAM;
    u8              TESG2;
    u8              TESG1;
    FunctionalState GTS;
    u8              CDCLK;
    u8              CLOSE_OPEN_CLK;
    u8              RXINTEN;
    u8              CBP;
} CAN_Basic_InitTypeDef;

////////////////////////////////////////////////////////////////////////////////
/// @brief  CAN_Peli init structure definition
////////////////////////////////////////////////////////////////////////////////
typedef struct {
    u8              SJW;
    u8              BRP;
    FlagStatus      SAM;
    u8              TESG2;
    u8              TESG1;
    FunctionalState LOM;
    FunctionalState STM;
    FunctionalState SM;
    FunctionalState SRR;
    u32             EWLR;
} CAN_Peli_InitTypeDef;

////////////////////////////////////////////////////////////////////////////////
/// @brief  CAN_Basic filter init structure definition
////////////////////////////////////////////////////////////////////////////////

typedef struct {
    u8 CAN_FilterId;      ///< Specifies the filter identification number. This parameter can be a value between 0x00 and 0xFF.
    u8 CAN_FilterMaskId;  ///< Specifies the filter mask number or identification number, This parameter can be a value between
    ///< 0x00 and 0xFF.
} CAN_Basic_FilterInitTypeDef;

////////////////////////////////////////////////////////////////////////////////
/// @brief  CAN_Peli filter init structure definition
////////////////////////////////////////////////////////////////////////////////

typedef struct {
    u8 AFM;
    u8 CAN_FilterId0;  ///< Specifies the filter identification number, This parameter can be a value between 0x00 and 0xFF
    u8 CAN_FilterId1;
    u8 CAN_FilterId2;
    u8 CAN_FilterId3;
    u8 CAN_FilterMaskId0;  ///< Specifies the filter mask number or identification number, This parameter can be a value between
    ///< 0x00 and 0xFF
    u8 CAN_FilterMaskId1;
    u8 CAN_FilterMaskId2;
    u8 CAN_FilterMaskId3;
} CAN_Peli_FilterInitTypeDef;

////////////////////////////////////////////////////////////////////////////////
/// @brief  CAN_Basic Tx message structure definition
////////////////////////////////////////////////////////////////////////////////

typedef struct {
    u8 IDH;      ///< Specifies the standard high identifier. This parameter can be a value between 0 to 0xFF.
    u8 IDL;      ///< Specifies the standard low identifier. This parameter can be a value between 0 to 0x7.
    u8 RTR;      ///< Specifies the type of frame for the message that will be transmitted. This parameter can be @TransFrame.
    u8 DLC;      ///< Specifies the length of the frame that will be transmitted. This parameter can be a value between 0 to 8.
    u8 Data[8];  ///< Contains the data to be transmitted. It ranges from 0 to 0xFF.
} CanBasicTxMsg;

////////////////////////////////////////////////////////////////////////////////
/// @brief  CAN_Basic Rx message structure definition
////////////////////////////////////////////////////////////////////////////////

typedef struct {
    u16 ID;       ///< Specifies the standard identifier. This parameter can be a value between 0 to 0x7FF.
    u8  RTR;      ///< Specifies the type of frame for the received message. This parameter can be a value of @ref TransFrame
    u8  DLC;      ///< Specifies the length of the frame that will be received. This parameter can be a value between 0 to 8
    u8  Data[8];  ///< Contains the data to be received. It ranges from 0 to  0xFF.
} CanBasicRxMsg;

///////////////////////////////////////////////////////////////////////////////
/// @brief  CAN_Peli_Tx message structure definition
///////////////////////////////////////////////////////////////////////////////

typedef struct {
    u8 IDLL;  ///< Specifies the extended identifier.
    ///< This parameter can be a value between 0 to 0xFF.
    u8 IDLH;
    u8 IDHL;
    u8 IDHH;
    u8 FF;   ///< Specifies the type of identifier for the message that will be transmitted. This parameter can be a value of @ref
    ///< CAN_identifier_type
    u8 RTR;  ///< Specifies the type of frame for the message that will be transmitted. This parameter can be a value of @ref
    ///< TransFrame.
    u8 DLC;  ///< Specifies the length of the frame that will be transmitted. This parameter can be a value between 0 to 8.
    u8 Data[8];  ///< Contains the data to be transmitted. It ranges from 0 to 0xFF.
} CanPeliTxMsg;

////////////////////////////////////////////////////////////////////////////////
/// @brief  CAN Rx message structure definition
////////////////////////////////////////////////////////////////////////////////
typedef struct {
    u32 ID;  ///< Specifies the extended identifier. This parameter can be a value between 0 to 0x1FFFFFFF.
    u8  FF;  ///< Specifies the type of identifier for the message that will be received. This parameter can be a value of @ref
    ///< CAN_identifier_type.
    u8 RTR;  ///< Specifies the type of frame for the received message. This parameter can be a value of @ref TransFrame.
    u8 DLC;  ///< Specifies the length of the frame that will be received. This parameter can be a value between 0 to 8.
    u8 Data[8];  ///< Contains the data to be received. It ranges from 0 to0xFF.
} CanPeliRxMsg;

/// @}

////////////////////////////////////////////////////////////////////////////////
/// @defgroup  CAN_Exported_Constants
/// @{

////////////////////////////////////////////////////////////////////////////////
/// @defgroup  parasmeter_of_CAN_transmission_register
/// @{
#define CANTXFAILED (0x00U)   ///< CAN transmission failed
#define CANTXOK (0x01U)       ///< CAN transmission succeeded
#define CANTXPENDING (0x02U)  ///< CAN transmission pending
#define CAN_NO_MB (0x04U)     ///< CAN cell did not provide an empty mailbox
/// @}


/// @}

////////////////////////////////////////////////////////////////////////////////
/// @defgroup CAN_Exported_Variables
/// @{
#ifdef _HAL_CAN_C_

#define GLOBAL
#else
#define GLOBAL extern
#endif

#undef GLOBAL
/// @}

////////////////////////////////////////////////////////////////////////////////
/// @defgroup CAN_Exported_Functions
/// @{

// Basic and Peli Work all need function ---------------------------------------

void CAN_Mode_Cmd(CAN_TypeDef* can, u32 mode);
void CAN_ResetMode_Cmd(CAN_TypeDef* can, FunctionalState state);
void CAN_ClearDataOverflow(CAN_TypeDef* can);
void CAN_ClearITPendingBit(CAN_TypeDef* can);

// Basic Work function ---------------------------------------------------------
void CAN_DeInit(CAN_TypeDef* can);
void CAN_FilterInit(CAN_Basic_FilterInitTypeDef* basic_filter_init_struct);
void CAN_StructInit(CAN_Basic_InitTypeDef* basic_init_struct);
void CAN_ITConfig(CAN_TypeDef* can, u32 it, FunctionalState state);
void CAN_CancelTransmit(CAN_TypeDef* can);
void CAN_FIFORelease(CAN_TypeDef* can);
void CAN_Receive(CAN_TypeDef* can, CanBasicRxMsg* basic_receive_message);

u8 CAN_Transmit(CAN_TypeDef* can, CanBasicTxMsg* basic_transmit_message);
u8 CAN_Init(CAN_TypeDef* can, CAN_Basic_InitTypeDef* basic_init_struct);
u8 CAN_Sleep(CAN_TypeDef* can);
u8 CAN_WakeUp(CAN_TypeDef* can);

FlagStatus CAN_GetFlagStatus(CAN_TypeDef* can, u32 flag);
ITStatus   CAN_GetITStatus(CAN_TypeDef* can, u32 it);

// Peli Work function ----------------------------------------------------------
void CAN_Peli_SleepMode_Cmd(FunctionalState state);
void CAN_Peli_Init(CAN_Peli_InitTypeDef* init_struct);
void CAN_Peli_StructInit(CAN_Peli_InitTypeDef* peli_init_struct);
void CAN_Peli_FilterInit(CAN_Peli_FilterInitTypeDef* peli_filter_init_struct);
void CAN_Peli_FilterStructInit(CAN_Peli_FilterInitTypeDef* peli_filter_init_struct);
void CAN_Peli_Transmit(CanPeliTxMsg* peli_transmit_message);
void CAN_Peli_TransmitRepeat(CanPeliTxMsg* peli_transmit_message);
void CAN_Peli_Receive(CanPeliRxMsg* peli_receive_message);
void CAN_Peli_ITConfig(u32 it, FunctionalState state);
void CAN_AutoCfg_BaudParam(CAN_Peli_InitTypeDef* init_struct, u32 src_clk, u32 baud);

u32 CAN_Peli_GetRxFIFOInfo(void);
u8  CAN_Peli_GetLastErrorCode(void);
u8  CAN_Peli_GetReceiveErrorCounter(void);
u8  CAN_Peli_GetLSBTransmitErrorCounter(void);

ITStatus CAN_Peli_GetITStatus(u32 it);



/// @}

/// @}

/// @}

////////////////////////////////////////////////////////////////////////////////
#endif
////////////////////////////////////////////////////////////////////////////////