/******************************************************************************
* @file  :  hal_can.h
* @brief :  Header file of CAN HAL module.
* @ver   :  V1.0.0
* @date  :  2020
******************************************************************************/

#ifndef __HAL_CAN_H__
#define __HAL_CAN_H__

#include "hal.h"


/** 
  * @brief  CAN  init structure definition
  */
typedef struct
{
    uint32_t CAN_Mode;         /*!< Specifies the CAN operating mode.
                                This parameter can be a value of 
                                @ref CAN_mode  e.g:CAN_Mode_Normal   CAN_Mode_Normal*/ 
    
    uint32_t CAN_SJW;          /*!< Specifies the maximum number of time quanta 
                                the CAN hardware is allowed to lengthen or 
                                shorten a bit to perform resynchronization.
                                This parameter can be a value of 
                                @ref CAN_SJW  e.g:CAN_SJW_1tq--CAN_SJW_4tq*/
    
    uint32_t CAN_BRP ;          /*!< Specifies the number of time quanta in Bit 
                                Segment 1. This parameter can be a value between 0 and 63 */
    
    uint32_t CAN_TSEG1;          /*!< Specifies the number of time quanta in Bit 
                                Segment 1. This parameter can be a value of 
                                @ref CAN_TSEG1  e.g: CAN_TSEG1_1tq-CAN_TSEG1_16tq*/
    
    uint32_t CAN_TSEG2;          /*!< Specifies the number of time quanta in Bit 
                                Segment 2.This parameter can be a value of 
                                @ref CAN_TSEG2  e.g:CAN_TSEG1_1tq-CAN_TSEG16_tq*/
    
    uint32_t CAN_SAM ;           /*!< Specifies the CAN operating mode.
                                This parameter can be a value of 
                                @ref CAN_SAM e.g:CAN_SAM_1time  CAN_SAM_3time*/
                                
    uint32_t CAN_BOR ;          /*!< CAN BUS OFF ERROR RECOVER
                                @ref CAN_ABOM e.g:CAN_BOR_ENABLE  CAN_BOR_DISABLE*/ 
} CAN_InitTypeDef;


/** 
  * @brief  CAN filter init structure definition
  */

typedef struct
{
      uint32_t FilterBank;            /*!< Specifies the filter bank which will be initialized.
                                       For single CAN instance(14 dedicated filter banks),
                                       this parameter must be a number between Min_Data = 0 and Max_Data = 7*/
    
     uint32_t   FilterMode;            /*!< Specifies the filter mode to be initialized.
                                        This parameter can be a value of 
                                        @ref CAN_filter_mode  e.g:CAN_FilterMode_Dual    CAN_FilterMode_Single*/
    
    uint32_t FilterId1;             /*!< Specifies the filter identification number 
                                        This parameter can be a value between 0x0000 and 0x1FFFFFFF */
    
    uint32_t FilterId2;             /*!< Specifies the filter identification number 
                                        only CAN_FilterMode=CAN_FilterMode_Dual Enable
                                        This parameter can be a value between 0x0000 and 0x1FFFFFFF */
    
    uint32_t FilterMaskId1;         /*!< Specifies the filter identification mask number 
                                        This parameter can be a value between 0x0000 and 0x1FFFFFFF */
    
    uint32_t FilterMaskId2;         /*!< Specifies the filter identification mask number 
                                        only CAN_FilterMode=CAN_FilterMode_Dual Enable
                                        This parameter can be a value between 0x0000 and 0x1FFFFFFF */
                                        
  
   uint32_t FilterActivation;      /*!< Enable or disable the filter.
                                       This parameter can be a value of @ref CAN_filter_activation */                                      
                                        
} CAN_FilterInitTypeDef;



/** 
  * @brief  CAN RxTxMessege structure definition
  */
typedef struct
{
    uint32_t StdId;                     /*!< Specifies the standard identifier.
                                        This parameter can be a value between 0 to 0x7FF. */
    
    uint32_t ExtId;                     /*!< Specifies the extended identifier.
                                        This parameter can be a value between 0 to 0x1FFFFFFF. */
    
    uint32_t IDE;                        /*!< Specifies the type of identifier for the message that 
                                        will be transmitted. This parameter can be a value 
                                        of @ref CAN_identifier_type  e.g: CAN_Id_Standard  CAN_Id_Extended*/
    
    uint32_t RTR;                        /*!< Specifies the type of frame for the message that will 
                                        be transmitted. This parameter can be a value of 
                                        @ref CAN_remote_transmission    e.g: CAN_RTR_Data  CAN_RTR_Remote */
    
    uint32_t DLC;                        /*!< Specifies the length of the frame that will be 
                                        transmitted. This parameter can be a value between 0 to 8 */
    
    uint8_t Data[8];                    /*!< Contains the data to be transmitted. It ranges from 0 to 0xFF. */
} CanTxRxMsg;


/**
  * @brief  CAN handle Structure definition
  */
typedef struct __CAN_HandleTypeDef
{
    CAN_TypeDef         *Instance;                 /*!< Register base address */
    
    CAN_InitTypeDef      Init;                      /*!< CAN required parameters */
    
    CanTxRxMsg          *RxMessage;                 /*!< CAN RxMessage */
    
    void (*CAN_ReceiveIT_Callback)(struct __CAN_HandleTypeDef *hcan);     /* CAN  ReceiveIT complete callback */ 
    
    void (*CAN_TransmitIT_Callback)(struct __CAN_HandleTypeDef *hcan);     /* CAN TransmitIT complete callback */ 
    
} CAN_HandleTypeDef;


#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE))

#define IS_CAN_ALL_PERIPH(PERIPH) (((PERIPH) == CAN1) || \
                                   ((PERIPH) == CAN2))

/** @defgroup CAN_identifier_type 
  * @{
  */

#define CAN_Id_Standard             ((uint32_t)0x00000000)  /*!< Standard Id */
#define CAN_Id_Extended             ((uint32_t)0x00000001)  /*!< Extended Id */
#define IS_CAN_IDTYPE(IDTYPE) (((IDTYPE) == CAN_Id_Standard) || \
                               ((IDTYPE) == CAN_Id_Extended))
/**
  * @}
  */

/** @defgroup CAN_remote_transmission
  * @{
  */
#define CAN_RTR_Data                ((uint32_t)0x00000000)  /*!< Data frame */
#define CAN_RTR_Remote              ((uint32_t)0x00000001)  /*!< Remote frame */
#define IS_CAN_RTR(RTR) (((RTR) == CAN_RTR_Data) || ((RTR) == CAN_RTR_Remote))
/**
  * @}
  */
  
 /** @defgroup CAN_filter_activation CAN Filter Activation
  * @{
  */
#define CAN_FILTER_DISABLE          (0x00000000U)  /*!< Disable filter */
#define CAN_FILTER_ENABLE           (0x00000001U)  /*!< Enable filter  */
/**
  * @}
  */ 
  

#define IS_CAN_STDID(STDID)   ((STDID) <= ((uint32_t)0x7FF))
#define IS_CAN_EXTID(EXTID)   ((EXTID) <= ((uint32_t)0x1FFFFFFF))
#define IS_CAN_DLC(DLC)       ((DLC) <= ((uint8_t)0x08))


#define IS_CAN_GET_FLAG(FLAG) (((FLAG) == CAN_SR_RBS)  || ((FLAG) == CAN_SR_DOS)   || \
                               ((FLAG) == CAN_SR_TBS)  || ((FLAG) == CAN_SR_TCS)   || \
                               ((FLAG) == CAN_SR_RS)  || ((FLAG) == CAN_SR_TS)  || \
                               ((FLAG) == CAN_SR_ES)  || ((FLAG) == CAN_SR_BS))	

#define IS_CAN_BRP(BRP) 	(((BRP) >= 0) && ((BRP) <= 63))


/**
  * @defgroup CAN_BOR
  * @{
  */  
#define CAN_BOR_ENABLE         ((uint8_t)0x00) /*!< BUS OFF RECOVER ENABLE */
#define CAN_BOR_DISABLE        ((uint8_t)0x01) /*!< BUS OFF RECOVER DISABLE */
/**
  * @}
  */


/**
  * @defgroup CAN_Operating_Mode 
  * @{
  */  
#define CAN_OperatingMode_Normal                     ((uint32_t)0x00000000) /*!< Normal mode */
#define CAN_OperatingMode_Initialization             ((uint32_t)CAN_MOD_RM) /*!< Initialization mode */
#define CAN_OperatingMode_Listen                     ((uint32_t)CAN_MOD_LOM) /*!< Listen mode */
#define CAN_OperatingMode_SelfTest                   ((uint32_t)CAN_MOD_STM) /*!< Listen mode */
#define CAN_OperatingMode_Sleep                      ((uint32_t)CAN_MOD_SM) /*!< sleep mode */
#define CAN_OperatingMode_LOOPBACK                   ((uint32_t)CAN_MOD_LBKM)                   /*!< Loopback mode */
#define CAN_OperatingMode_SILENT                     ((uint32_t)CAN_MOD_SILM)                   /*!< Silent mode   */
#define CAN_OperatingMode_SILENT_LOOPBACK            ((uint32_t)(CAN_MOD_LBKM | CAN_MOD_SILM))  /*!< Loopback combined with silent mode */

#define IS_CAN_OPERATING_MODE(MODE) (((MODE) == CAN_OperatingMode_Initialization) ||\
                                    ((MODE) == CAN_OperatingMode_Normal)|| \
                                    ((MODE) == CAN_OperatingMode_SelfTest)|| \
                                    ((MODE) == CAN_OperatingMode_Sleep)||\
                                    ((MODE) == CAN_OperatingMode_Listen)||\
                                    ((MODE) == CAN_OperatingMode_LOOPBACK)||\
                                    ((MODE) == CAN_OperatingMode_SILENT)||\
                                    ((MODE) == CAN_OperatingMode_SILENT_LOOPBACK))
/**
  * @}
  */

/** @defgroup CAN_SAM 
  * @{
  */

#define CAN_SAM_1time       ((uint8_t)0x00)  /*!< 1 time quantum */
#define CAN_SAM_3time       ((uint8_t)0x01)  /*!< 2 time quantum */

#define IS_CAN_SAM(SAM)     (((SAM) == CAN_SAM_1time) || ((SAM) == CAN_SAM_3time))
/**
  * @}
  */


/** @defgroup CAN_synchronisation_jump_width 
  * @{
  */

#define CAN_SJW_1tq         ((uint8_t)0x00)  /*!< 1 time quantum */
#define CAN_SJW_2tq         ((uint8_t)0x01)  /*!< 2 time quantum */
#define CAN_SJW_3tq         ((uint8_t)0x02)  /*!< 3 time quantum */
#define CAN_SJW_4tq         ((uint8_t)0x03)  /*!< 4 time quantum */

#define IS_CAN_SJW(SJW) (((SJW) == CAN_SJW_1tq) || ((SJW) == CAN_SJW_2tq)|| \
                         ((SJW) == CAN_SJW_3tq) || ((SJW) == CAN_SJW_4tq))
/**
  * @}
  */
	
	/** @defgroup CAN_time_quantum_in_bit_segment_1 
  * @{
  */

#define CAN_TSEG1_1tq       ((uint8_t)0x00)  /*!< 1 time quantum */
#define CAN_TSEG1_2tq       ((uint8_t)0x01)  /*!< 2 time quantum */
#define CAN_TSEG1_3tq       ((uint8_t)0x02)  /*!< 3 time quantum */
#define CAN_TSEG1_4tq       ((uint8_t)0x03)  /*!< 4 time quantum */
#define CAN_TSEG1_5tq       ((uint8_t)0x04)  /*!< 5 time quantum */
#define CAN_TSEG1_6tq       ((uint8_t)0x05)  /*!< 6 time quantum */
#define CAN_TSEG1_7tq       ((uint8_t)0x06)  /*!< 7 time quantum */
#define CAN_TSEG1_8tq       ((uint8_t)0x07)  /*!< 8 time quantum */
#define CAN_TSEG1_9tq       ((uint8_t)0x08)  /*!< 9 time quantum */
#define CAN_TSEG1_10tq      ((uint8_t)0x09)  /*!< 10 time quantum */
#define CAN_TSEG1_11tq      ((uint8_t)0x0A)  /*!< 11 time quantum */
#define CAN_TSEG1_12tq      ((uint8_t)0x0B)  /*!< 12 time quantum */
#define CAN_TSEG1_13tq      ((uint8_t)0x0C)  /*!< 13 time quantum */
#define CAN_TSEG1_14tq      ((uint8_t)0x0D)  /*!< 14 time quantum */
#define CAN_TSEG1_15tq      ((uint8_t)0x0E)  /*!< 15 time quantum */
#define CAN_TSEG1_16tq      ((uint8_t)0x0F)  /*!< 16 time quantum */

#define IS_CAN_TSEG1(TSEG1) ((TSEG1) <= CAN_TSEG1_16tq)
/**
  * @}
  */

/** @defgroup CAN_time_quantum_in_bit_segment_2 
  * @{
  */

#define CAN_TSEG2_1tq       ((uint8_t)0x00)  /*!< 1 time quantum */
#define CAN_TSEG2_2tq       ((uint8_t)0x01)  /*!< 2 time quantum */
#define CAN_TSEG2_3tq       ((uint8_t)0x02)  /*!< 3 time quantum */
#define CAN_TSEG2_4tq       ((uint8_t)0x03)  /*!< 4 time quantum */
#define CAN_TSEG2_5tq       ((uint8_t)0x04)  /*!< 5 time quantum */
#define CAN_TSEG2_6tq       ((uint8_t)0x05)  /*!< 6 time quantum */
#define CAN_TSEG2_7tq       ((uint8_t)0x06)  /*!< 7 time quantum */
#define CAN_TSEG2_8tq       ((uint8_t)0x07)  /*!< 8 time quantum */
#define IS_CAN_TSEG2(TSEG) ((TSEG) <= CAN_TSEG2_8tq)
/**
  * @}
  */

	  
/** @defgroup CAN_filter_mode 
  * @{
  */
#define CAN_FilterMode_Dual         ((uint8_t)0x00)  /*!< identifier list mode */
#define CAN_FilterMode_Single       ((uint8_t)0x01)  /*!< identifier/mask mode */
#define IS_CAN_FILTER_MODE(MODE) (((MODE) == CAN_FilterMode_Dual) || \
                                  ((MODE) == CAN_FilterMode_Single))

	/**
  * @}
  */

/** 
  * @brief  CAN ErrorCode enum
  */                                    
typedef enum
{
    CAN_BIT_ERR = 0,
    CAN_FORMAT_ERR,
    CAN_BIT_STUFFING_ERR,
    CAN_OTHER_ERRS                  //see @CAN_ERR_SegCode_Enum
}CAN_ErrCode_Enum;


/** 
  * @brief  CAN SegCode enum
  */ 
typedef enum
{
    CAN_SEGCODE_ERR_ID28_21 = 2,        //00010
    CAN_SEGCODE_ERR_SOF,                //00011
    CAN_SEGCODE_ERR_SRTR,               //00100
    CAN_SEGCODE_ERR_IDE,                //00101
    CAN_SEGCODE_ERR_ID20_18,            //00110
    CAN_SEGCODE_ERR_ID17_13,            //00111
    CAN_SEGCODE_ERR_CRC,                //01000
    CAN_SEGCODE_ERR_RSV,                //01001
    CAN_SEGCODE_ERR_DATA,               //01010
    CAN_SEGCODE_ERR_DLC,                //01011
    CAN_SEGCODE_ERR_RTR,                //01100
    CAN_SEGCODE_ERR_RSV2,               //01101
    CAN_SEGCODE_ERR_ID4_0,              //01110
    CAN_SEGCODE_ERR_ID12_5,             //01111
    CAN_SEGCODE_ERR_RSV3,               //10000
    CAN_SEGCODE_ERR_ACTIVE,             //10001
    CAN_SEGCODE_ERR_INTERVAL,           //10010
    CAN_SEGCODE_ERR_DOMINANT_TOLERANCE, //10011
    CAN_SEGCODE_ERR_RSV4,               //10100
    CAN_SEGCODE_ERR_RSV5,               //10101
    CAN_SEGCODE_ERR_PASSIVE,            //10110
    CAN_SEGCODE_ERR_DELIMITER,          //10111
    CAN_SEGCODE_ERR_CRC_DELIMITER,      //11000
    CAN_SEGCODE_ERR_ACK,                //11001
    CAN_SEGCODE_ERR_EOF,                //11010
    CAN_SEGCODE_ERR_ACK_DELIMITER,      //11011
    CAN_SEGCODE_ERR_OVERLOAD,           //11100
    
}CAN_ERR_SegCode_Enum;


/** 
  * @brief  CAN ErrorCode sturcture. see @ref register @CAN_ECCR
  */ 
typedef struct {
    uint8_t                 ALC;
    CAN_ErrCode_Enum        ErrCode;
    uint8_t                 ErrDirection;
    CAN_ERR_SegCode_Enum    SegCode;
}CAN_ErrCodeInfo_t;


/** 
  * @brief  CAN ErrorCnt sturcture. see @ref register @CAN_ERRCNTR
  */ 
typedef struct {
    uint8_t                 EWL;
    uint8_t                 TXERR_CNT;
    uint8_t                 RXERR_CNT;
}CAN_ErrCnt_t;

/**
  * @}
  */
/* Initialization and Configuration functions *********************************/
HAL_StatusTypeDef HAL_CAN_Init(CAN_HandleTypeDef *hcan);
HAL_StatusTypeDef HAL_CAN_DeInit(CAN_HandleTypeDef *hcan);
void HAL_CAN_MspInit(CAN_HandleTypeDef *hcan);
void HAL_CAN_MspDeInit(CAN_HandleTypeDef *hcan);

void HAL_CAN_ConfigFilter(CAN_HandleTypeDef *hcan,CAN_FilterInitTypeDef* CAN_FilterInitStruct);

/* transceive functions *********************************************************/
HAL_StatusTypeDef HAL_CAN_Transmit(CAN_HandleTypeDef *hcan, CanTxRxMsg* TxMessage, uint32_t Timeout);
void HAL_CAN_CancelTransmit(CAN_HandleTypeDef *hcan);
HAL_StatusTypeDef HAL_CAN_Receive(CAN_HandleTypeDef *hcan, CanTxRxMsg* RxMessage, uint32_t Timeout);
HAL_StatusTypeDef HAL_CAN_Receive_IT(CAN_HandleTypeDef *hcan, CanTxRxMsg* RxMessage);


int8_t HAL_CAN_GetReceiveFiFoCounter(CAN_HandleTypeDef *hcan);
int8_t HAL_CAN_GetReceiveFiFoAddr(CAN_HandleTypeDef *hcan);
void HAL_CAN_ReleaseReceiveFIFO(CAN_HandleTypeDef *hcan);
void HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, CanTxRxMsg* RxMessage);

/* Operation modes functions **************************************************/
HAL_StatusTypeDef HAL_CAN_OperatingModeRequest(CAN_HandleTypeDef *hcan, uint8_t CAN_OperatingMode);

void HAL_CAN_ClearOverload(CAN_HandleTypeDef *hcan);

void HAL_CAN_SelfReceive(CAN_HandleTypeDef *hcan);

HAL_StatusTypeDef HAL_CAN_Sleep(CAN_HandleTypeDef *hcan);

HAL_StatusTypeDef HAL_CAN_WakeUp(CAN_HandleTypeDef *hcan);

/* Error Code & Error count management functions **********************************/
HAL_StatusTypeDef HAL_CAN_GetErrorCode(CAN_HandleTypeDef *hcan, CAN_ErrCodeInfo_t *pErrCode);
HAL_StatusTypeDef HAL_CAN_GetErrorCNT(CAN_HandleTypeDef *hcan, CAN_ErrCnt_t *pErrCnt);

void HAL_CAN_IRQHandler(CAN_HandleTypeDef *hcan);

#endif
