/* Copyright Statement:
 *
 * This software/firmware and related documentation ("AutoChips Software") are
 * protected under relevant copyright laws. The information contained herein is
 * confidential and proprietary to AutoChips Inc. and/or its licensors. Without
 * the prior written permission of AutoChips inc. and/or its licensors, any
 * reproduction, modification, use or disclosure of AutoChips Software, and
 * information contained herein, in whole or in part, shall be strictly
 * prohibited.
 *
 * AutoChips Inc. (C) 2021. All rights reserved.
 *
 * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
 * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("AUTOCHIPS SOFTWARE")
 * RECEIVED FROM AUTOCHIPS AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
 * ON AN "AS-IS" BASIS ONLY. AUTOCHIPS EXPRESSLY DISCLAIMS ANY AND ALL
 * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
 * NONINFRINGEMENT. NEITHER DOES AUTOCHIPS PROVIDE ANY WARRANTY WHATSOEVER WITH
 * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
 * INCORPORATED IN, OR SUPPLIED WITH THE AUTOCHIPS SOFTWARE, AND RECEIVER AGREES
 * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
 * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
 * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN AUTOCHIPS
 * SOFTWARE. AUTOCHIPS SHALL ALSO NOT BE RESPONSIBLE FOR ANY AUTOCHIPS SOFTWARE
 * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
 * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND AUTOCHIPS'S
 * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE AUTOCHIPS SOFTWARE
 * RELEASED HEREUNDER WILL BE, AT AUTOCHIPS'S OPTION, TO REVISE OR REPLACE THE
 * AUTOCHIPS SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
 * CHARGE PAID BY RECEIVER TO AUTOCHIPS FOR SUCH AUTOCHIPS SOFTWARE AT ISSUE.
 */

/*!
 * @file can_hw.h
 *
 * @brief This file provides CAN hardware definition and declaration.
 *
 */

/* PRQA S 4304 EOF */ /* Type conversion. */

#ifndef CAN_HW_H
#define CAN_HW_H

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

/* ===========================================  Includes  =========================================== */
#include "can_drv.h"

/* ============================================  Define  ============================================ */
#define CAN_MAX_S_SEG_1    (0xFFUL)        /*!< CAN max slow bitrate seg 1 */
#define CAN_MAX_S_SEG_2    (0x7FUL)        /*!< CAN max slow bitrate seg 2 */
#define CAN_MAX_S_SJW      (0x7FUL)        /*!< CAN max slow bitrate sjw */
#define CAN_MAX_S_PRESC    (0xFFUL)        /*!< CAN max slow bitrate prescaler */
#define CAN_MAX_F_SEG_1    (0x1FUL)        /*!< CAN max fast bitrate seg 1 */
#define CAN_MAX_F_SEG_2    (0xFUL)         /*!< CAN max fast bitrate seg 2 */
#define CAN_MAX_F_SJW      (0xFUL)         /*!< CAN max fast bitrate sjw */
#define CAN_MAX_F_PRESC    (0xFFUL)        /*!< CAN max fast bitrate prescaler */

/* ===========================================  Typedef  ============================================ */

/* ==========================================  Variables  =========================================== */

/* ====================================  Functions declaration  ===================================== */
/*!
 * @brief Write TBUF.
 *
 * @param[in] base: CAN module
 * @param[in] txBuf: pointer to transmission buffer
 * @param[in] length: number of buffer bytes
 * @return none
 */
void CAN_WriteTbuf(CAN_Type *base, const uint8_t *txBuf, uint8_t length);

/*!
 * @brief Write TBUF message data.
 *
 * @param[in] base: CAN module
 * @param[in] txData: pointer to transmission data
 * @param[in] length: number of message data bytes
 * @return none
 */
void CAN_WriteTbufData(CAN_Type *base, const uint8_t *txData, uint8_t length);

/*!
 * @brief Read RBUF.
 *
 * @param[in] base: CAN module
 * @param[out] rxBuf: pointer to receive buffer
 * @param[in] length: number of buffer bytes
 * @return none
 */
void CAN_ReadRbuf(CAN_Type *base, uint8_t *rxBuf, uint8_t length);

/*!
 * @brief Read RBUF message data.
 *
 * @param[in] base: CAN module
 * @param[out] rxData: pointer to receive data
 * @param[in] length: number of message data bytes
 * @return none
 */
void CAN_ReadRbufData(CAN_Type *base, uint8_t *rxData, uint8_t length);

/*!
 * @brief Compute message payload size.
 *
 * @param[in] dlcValue: DLC value
 * @return Payload size
 */
uint8_t CAN_ComputePayloadSize(uint8_t dlcValue);

/*!
 * @brief Compute message DLC value.
 *
 * @param[in] payloadSize: payload size
 * @return DLC value
 */
uint8_t CAN_ComputeDlcValue(uint8_t payloadSize);

/*!
 * @brief Start transmit frame in the TBUF.
 *
 * @param[in] base: CAN module
 * @param[in] type: CAN transmit buffer type
 *            - CAN_TRANSMIT_PRIMARY
 *            - CAN_TRANSMIT_SECONDARY
 * @param[in] amount: transmit secondary all or one frames
 *            - CAN_TRANSMIT_SEC_ALL
 *            - CAN_TRANSMIT_SEC_ONE
 * @return none
 */
void CAN_StartTransmit(CAN_Type *base, can_transmit_buff_t type, can_transmit_sec_amount_t amount);

/*!
 * @brief Abort transmitting.
 *
 * @param[in] base: CAN module
 * @param[in] type: CAN transmit buffer type
 *            - CAN_TRANSMIT_PRIMARY
 *            - CAN_TRANSMIT_SECONDARY
 * @return none
 */
void CAN_AbortTransmit(CAN_Type *base, can_transmit_buff_t type);

/*!
 * @brief Set acceptance filter state.
 *
 * @param[in] base: CAN module
 * @param[in] index: filter index
 * @param[in] enable: filter enable state
 * @return none
 */
void CAN_SetFilterEnable(CAN_Type *base, uint8_t index, bool enable);

/* =====================================  Functions definition  ===================================== */
/*!
 * @brief Check transmit is busy.
 *
 * @param[in] base: CAN module
 * @param[in] type: CAN transmit buffer type
 *            - CAN_TRANSMIT_PRIMARY
 *            - CAN_TRANSMIT_SECONDARY
 * @return transmit busy flag
 *         - false: not busy or STB is not full
 *         - true: is busy or STB is full
 */
static inline bool CAN_IsTransmitBusy(CAN_Type *base, can_transmit_buff_t type)
{
    if (CAN_TRANSMIT_PRIMARY == type)
    {
        return (((base->CTRL0 & CAN_CTRL0_TPE_Msk) >> CAN_CTRL0_TPE_Pos) != 0U);
    }
    else
    {
        return (bool)((uint32_t)CAN_TSSTAT_FULL == ((base->CTRL0 & CAN_CTRL0_TSSTAT_Msk) >> CAN_CTRL0_TSSTAT_Pos));
    }
}

/*!
 * @brief Check whether is transmitting.
 *
 * @param[in] base: CAN module
 * @param[in] type: CAN transmit buffer type
 *            - CAN_TRANSMIT_PRIMARY
 *            - CAN_TRANSMIT_SECONDARY
 * @return transmitting status
 *         - false: not transmitting
 *         - true: is transmitting
 */
static inline bool CAN_IsTransmitting(CAN_Type *base, can_transmit_buff_t type)
{
    if (CAN_TRANSMIT_PRIMARY == type)
    {
        return (((base->CTRL0 & CAN_CTRL0_TPE_Msk) >> CAN_CTRL0_TPE_Pos) != 0U);
    }
    else
    {
        return ((base->CTRL0 & (CAN_CTRL0_TSALL_Msk | CAN_CTRL0_TSONE_Msk)) != 0U);
    }
}

/*!
 * @brief Check transmission complete flag.
 *
 * @param[in] base: CAN module
 * @param[in] type: CAN transmit buffer type
 *            - CAN_TRANSMIT_PRIMARY
 *            - CAN_TRANSMIT_SECONDARY
 * @return Transmit status
 */
static inline bool CAN_IsTransmitDone(CAN_Type *base, can_transmit_buff_t type)
{
    if (CAN_TRANSMIT_PRIMARY == type)
    {
        return (((base->CTRL1 & CAN_CTRL1_TPIF_Msk) >> CAN_CTRL1_TPIF_Pos) != 0U);
    }
    else
    {
        return (((base->CTRL1 & CAN_CTRL1_TSIF_Msk) >> CAN_CTRL1_TSIF_Pos) != 0U);
    }
}

/*!
 * @brief Clear transmission complete flag.
 *
 * @param[in] base: CAN module
 * @param[in] type: CAN transmit buffer type
 *            - CAN_TRANSMIT_PRIMARY
 *            - CAN_TRANSMIT_SECONDARY
 * @return none
 */
static inline void CAN_ClearTransmitFlag(CAN_Type *base, can_transmit_buff_t type)
{
    if (CAN_TRANSMIT_PRIMARY == type)
    {
        base->CTRL1 |= CAN_CTRL1_TPIF_Msk;
    }
    else
    {
        base->CTRL1 |= CAN_CTRL1_TSIF_Msk;
    }
}

/*!
 * @brief Get RBUF message ID.
 *
 * @param[in] base: CAN module
 * @return Message id
 */
static inline uint32_t CAN_GetRbufId(CAN_Type *base)
{
    return (base->RBUF.ID_ESI);
}

/*!
 * @brief Set RBUF message control.
 *
 * @param[in] base: CAN module
 * @return Message control
 */
static inline uint32_t CAN_GetRbufCtrl(CAN_Type *base)
{
    return (base->RBUF.CTRL);
}

/*!
 * @brief Set TBUF message ID.
 *
 * @param[in] base: CAN module
 * @param[in] id: message id
 * @return none
 */
static inline void CAN_SetTbufId(CAN_Type *base, uint32_t id)
{
    base->TBUF.ID_ESI = id;
}

/*!
 * @brief Set TBUF message control.
 *
 * @param[in] base: CAN module
 * @param[in] ctrl: message control
 * @return none
 */
static inline void CAN_SetTbufCtrl(CAN_Type *base, uint32_t ctrl)
{
    base->TBUF.CTRL = ctrl;
}

/*!
 * @brief Get transmission time stamp value.
 *
 * @param[in] base: CAN module
 * @return Transmission time stamp value
 */
static inline uint32_t CAN_GetTransTimeStamp(CAN_Type *base)
{
    return (base->TBUF.TS[0U]);
}

/*!
 * @brief Check bus off status.
 *
 * @param[in] base: CAN module
 * @return Bus off status
 */
static inline bool CAN_IsBusOff(CAN_Type *base)
{
    return ((base->CTRL0 & CAN_CTRL0_BUSOFF_Msk) != 0U);
}

/*!
 * @brief Forced exit from bus off status.
 *
 * @param[in] base: CAN module
 * @return none
 */
static inline void CAN_ExitBusOff(CAN_Type *base)
{
    base->CTRL0 &= ~CAN_CTRL0_BUSOFF_Msk;
}

/*!
 * @brief Check transmit active status.
 *
 * @param[in] base: CAN module
 * @return Tactive status
 */
static inline bool CAN_IsTransActive(CAN_Type *base)
{
    return (((base->CTRL0 & CAN_CTRL0_TACTIVE_Msk) >> CAN_CTRL0_TACTIVE_Pos) != 0U);
}

/*!
 * @brief Check receive active status.
 *
 * @param[in] base: CAN module
 * @return Ractive status
 */
static inline bool CAN_IsRecvActive(CAN_Type *base)
{
    return (((base->CTRL0 & CAN_CTRL0_RACTIVE_Msk) >> CAN_CTRL0_RACTIVE_Pos) != 0U);
}

/*!
 * @brief Set transmission secondary single shot mode.
 *
 * @param[in] base: CAN module
 * @param[in] enable: tpss mode
 * @return none
 */
static inline void CAN_SetTsss(CAN_Type *base, bool enable)
{
    MODIFY_REG32(base->CTRL0, CAN_CTRL0_TSSS_Msk, CAN_CTRL0_TSSS_Pos, enable);
}

/*!
 * @brief Set transmission primary single shot mode.
 *
 * @param[in] base: CAN module
 * @param[in] enable: tpss mode
 * @return none
 */
static inline void CAN_SetTpss(CAN_Type *base, bool enable)
{
    MODIFY_REG32(base->CTRL0, CAN_CTRL0_TPSS_Msk, CAN_CTRL0_TPSS_Pos, enable);
}

/*!
 * @brief Set loopback internal mode.
 *
 * @param[in] base: CAN module
 * @param[in] enable: LBMI mode
 * @return none
 */
static inline void CAN_SetLoopbackIntMode(CAN_Type *base, bool enable)
{
    MODIFY_REG32(base->CTRL0, CAN_CTRL0_LBMI_Msk, CAN_CTRL0_LBMI_Pos, enable);
}

/*!
 * @brief Set loopback external mode.
 *
 * @param[in] base: CAN module
 * @param[in] enable: LBME mode
 * @return none
 */
static inline void CAN_SetLoopbackExtMode(CAN_Type *base, bool enable)
{
    MODIFY_REG32(base->CTRL0, CAN_CTRL0_LBME_Msk, CAN_CTRL0_LBME_Pos, enable);
}

/*!
 * @brief Set software reset state.
 *
 * @param[in] base: CAN module
 * @param[in] enable: reset state
 * @return none
 */
static inline void CAN_SetReset(CAN_Type *base, bool enable)
{
    MODIFY_REG32(base->CTRL0, CAN_CTRL0_RESET_Msk, CAN_CTRL0_RESET_Pos, enable);
}

/*!
 * @brief Get software reset state.
 *
 * @param[in] base: CAN module
 * @return Reset state
 */
static inline bool CAN_GetResetState(CAN_Type *base)
{
    return (((base->CTRL0 & CAN_CTRL0_RESET_Msk) >> CAN_CTRL0_RESET_Pos) != 0U);
}

/*!
 * @brief Set transceiver standby state.
 *
 * @param[in] base: CAN module
 * @param[in] enable: standby enable state
 * @return none
 */
static inline void CAN_SetStandby(CAN_Type *base, bool enable)
{
    MODIFY_REG32(base->CTRL0, CAN_CTRL0_STBY_Msk, CAN_CTRL0_STBY_Pos, enable);
}

/*!
 * @brief Get transceiver standby state.
 *
 * @param[in] base: CAN module
 * @return Standby state
 */
static inline bool CAN_GetStandbyState(CAN_Type *base)
{
    return (((base->CTRL0 & CAN_CTRL0_STBY_Msk) >> CAN_CTRL0_STBY_Pos) != 0U);
}

/*!
 * @brief Set listen only mode.
 *
 * @param[in] base: CAN module
 * @param[in] enable: LOM mode
 * @return none
 */
static inline void CAN_SetListenOnlyMode(CAN_Type *base, bool enable)
{
    MODIFY_REG32(base->CTRL0, CAN_CTRL0_LOM_Msk, CAN_CTRL0_LOM_Pos, enable);
}

/*!
 * @brief Set transmit buffer select.
 *
 * @param[in] base: CAN module
 * @param[in] type: CAN transmit buffer type
 *              - CAN_TRANSMIT_PRIMARY
 *              - CAN_TRANSMIT_SECONDARY
 * @return none
 */
static inline void CAN_SetTbufSelect(CAN_Type *base, can_transmit_buff_t type)
{
    base->CTRL0 = ((base->CTRL0 & (~(CAN_CTRL0_TSNEXT_Msk | CAN_CTRL0_TBSEL_Msk | CAN_CTRL0_TPE_Msk | CAN_CTRL0_TSALL_Msk | CAN_CTRL0_TSONE_Msk)))
                   | (((uint32_t)type << CAN_CTRL0_TBSEL_Pos) & CAN_CTRL0_TBSEL_Msk));
}

/*!
 * @brief Get transmit secondary buffer status.
 *
 * @param[in] base: CAN module
 * @return Transmit secondary buffer status
 */
static inline uint8_t CAN_GetTsbufStatus(CAN_Type *base)
{
    return (uint8_t)((base->CTRL0 & CAN_CTRL0_TSSTAT_Msk) >> CAN_CTRL0_TSSTAT_Pos);
}

/*!
 * @brief Check CAN bus idle status.
 *
 * @param[in] base: CAN module
 * @return Bus idle status
 */
static inline bool CAN_IsIdle(CAN_Type *base)
{
    return (((base->CTRL0 & CAN_CTRL0_IDLE_Msk) >> CAN_CTRL0_IDLE_Pos) != 0U);
}

/*!
 * @brief Set automatic recovering from bus off disable state.
 *
 * @param[in] base: CAN module
 * @param[in] enable: bus off recovery disable state
 * @return none
 */
static inline void CAN_SetBusOffRecDisable(CAN_Type *base, bool enable)
{
    MODIFY_REG32(base->CTRL0, CAN_CTRL0_BOREC_Msk, CAN_CTRL0_BOREC_Pos, enable);
}

/*!
 * @brief Set transmit secondary operation mode.
 *
 * @param[in] base: CAN module
 * @param[in] mode: Transmit secondary operation mode
 *              - CAN_TSMODE_FIFO
 *              - CAN_TSMODE_PRIORITY
 * @return none
 */
static inline void CAN_SetTransSecMode(CAN_Type *base, can_transmit_sec_mode_t mode)
{
    MODIFY_REG32(base->CTRL0, CAN_CTRL0_TSMODE_Msk, CAN_CTRL0_TSMODE_Pos, (uint32_t)mode);
}

/*!
 * @brief Select next transmit secondary buffer.
 *
 * @param[in] base: CAN module
 * @return none
 */
static inline void CAN_SelectNextTsbuf(CAN_Type *base)
{
    base->CTRL0 = ((base->CTRL0 & (~(CAN_CTRL0_TPE_Msk | CAN_CTRL0_TSALL_Msk | CAN_CTRL0_TSONE_Msk))) | CAN_CTRL0_TSNEXT_Msk);
}
/*!
 * @brief Set CANFD ISO mode.
 *
 * @param[in] base: CAN module
 * @param[in] enable: CAN FD ISO mode
 * @return none
 */
static inline void CAN_SetFdIso(CAN_Type *base, bool enable)
{
    MODIFY_REG32(base->CTRL0, CAN_CTRL0_FDISO_Msk, CAN_CTRL0_FDISO_Pos, enable);
}

/*!
 * @brief Get receive buffer status.
 *
 * @param[in] base: CAN module
 * @return Receive buffer status
 */
static inline uint8_t CAN_GetRbufStatus(CAN_Type *base)
{
    return (uint8_t)((base->CTRL0 & CAN_CTRL0_RSTAT_Msk) >> CAN_CTRL0_RSTAT_Pos);
}

/*!
 * @brief Set DMA receive enable.
 *
 * @param[in] base: CAN module
 * @param[in] enable: DMA receive enable state
 * @return none
 */
static inline void CAN_SetDmaRecv(CAN_Type *base, bool enable)
{
    MODIFY_REG32(base->CTRL0, CAN_CTRL0_DREN_Msk, CAN_CTRL0_DREN_Pos, enable);
}

/*!
 * @brief Set receive buffer store all data frames.
 *
 * @param[in] base: CAN module
 * @param[in] enable: receive buffer store all data frames state
 * @return none
 */
static inline void CAN_SetRball(CAN_Type *base, bool enable)
{
    MODIFY_REG32(base->CTRL0, CAN_CTRL0_RBALL_Msk, CAN_CTRL0_RBALL_Pos, enable);
}

/*!
 * @brief Release receive buffer.
 *
 * @param[in] base: CAN module
 * @return none
 */
static inline void CAN_ReleaseRbuf(CAN_Type *base)
{
    base->CTRL0 = ((base->CTRL0 & (~(CAN_CTRL0_TSNEXT_Msk | CAN_CTRL0_TPE_Msk | CAN_CTRL0_TSALL_Msk | CAN_CTRL0_TSONE_Msk))) | CAN_CTRL0_RREL_Msk);
}

/*!
 * @brief Get receive buffer overflow flag.
 *
 * @param[in] base: CAN module
 * @return Receive buffer overflow flag
 */
static inline uint8_t CAN_GetRbufOverflow(CAN_Type *base)
{
    return (uint8_t)((base->CTRL0 & CAN_CTRL0_ROV_Msk) >> CAN_CTRL0_ROV_Pos);
}

/*!
 * @brief Set receive buffer overflow mode.
 *
 * @param[in] base: CAN module
 * @param[in] mode: receive buffer overflow mode
 *              - CAN_ROM_OVER_WRITE
 *              - CAN_ROM_DISCARD
 * @return none
 */
static inline void CAN_SetRbufOverflowMode(CAN_Type *base, can_rbuf_overflow_mode_t mode)
{
    MODIFY_REG32(base->CTRL0, CAN_CTRL0_ROM_Msk, CAN_CTRL0_ROM_Pos, (uint32_t)mode);
}

/*!
 * @brief Set self acknowledge when LBME = 1.
 *
 * @param[in] base: CAN module
 * @param[in] enable: sack enable state
 * @return none
 */
static inline void CAN_SetSelfAck(CAN_Type *base, bool enable)
{
    MODIFY_REG32(base->CTRL0, CAN_CTRL0_SACK_Msk, CAN_CTRL0_SACK_Pos, enable);
}

/*!
 * @brief Set controller 1 register.
 *
 * @param[in] base: CAN module
 * @param[in] value: CAN controller 1 register value
 * @return none
 */
static inline void CAN_SetCtrl1(CAN_Type *base, uint32_t value)
{
    base->CTRL1 = value;
}

/*!
 * @brief Get CAN controller 1 register.
 *
 * @param[in] base: CAN module
 * @return Controller 1 register value
 */
static inline uint32_t CAN_GetCtrl1(CAN_Type *base)
{
    return base->CTRL1;
}

/*!
 * @brief Get transmit secondary buffer full flag.
 *
 * @param[in] base: CAN module
 * @return Transmit secondary buffer full flag
 */
static inline bool CAN_GetTsbufFullFlag(CAN_Type *base)
{
    return (((base->CTRL1 & CAN_CTRL1_TSFF_Msk) >> CAN_CTRL1_TSFF_Pos) != 0U);
}

/*!
 * @brief Set interrupt enable mask.
 *
 * @param[in] base: CAN module
 * @param[in] intMask: interrupt enable mask
 * @return none
 */
static inline void CAN_SetIntMask(CAN_Type *base, uint32_t intMask)
{
    MODIFY_REG32(base->CTRL1, CAN_IRQ_ALL_ENABLE_MSK, 0, intMask);
}

/*!
 * @brief Get error passive flag.
 *
 * @param[in] base: CAN module
 * @return Error passive flag
 */
static inline bool CAN_GetErrorPassiveFlag(CAN_Type *base)
{
    return (((base->CTRL1 & CAN_CTRL1_EPASS_Msk) >> CAN_CTRL1_EPASS_Pos) != 0U);
}

/*!
 * @brief Get error warning limit flag.
 *
 * @param[in] base: CAN module
 * @return Error warning limit flag
 */
static inline bool CAN_GetErrorWarningFlag(CAN_Type *base)
{
    return (((base->CTRL1 & CAN_CTRL1_EWARN_Msk) >> CAN_CTRL1_EWARN_Pos) != 0U);
}

/*!
 * @brief Set error warning limit.
 *
 * @param[in] base: CAN module
 * @param[in] ewl: error warning limit (0-15)
 * @return none
 */
static inline void CAN_SetErrorWarningLimit(CAN_Type *base, uint8_t ewl)
{
    MODIFY_REG32(base->CTRL1, CAN_CTRL1_EWL_Msk, CAN_CTRL1_EWL_Pos, ewl);
}

/*!
 * @brief Set Rbuf almost full warning limit.
 *
 * @param[in] base: CAN module
 * @param[in] afwl: almost full warning limit (1 - 12)
 * @return none
 */
static inline void CAN_SetAfwl(CAN_Type *base, uint8_t afwl)
{
    MODIFY_REG32(base->CTRL1, CAN_CTRL1_AFWL_Msk, CAN_CTRL1_AFWL_Pos, afwl);
}

/*!
 * @brief Set CAN normal slow bitrate.
 *
 * @param[in] base: CAN module
 * @param[in] bitrate: pointer to bitrate configuration
 * @return none
 */
static inline void CAN_SetSlowBitrate(CAN_Type *base, const can_time_segment_t *bitrate)
{
    DEVICE_ASSERT(bitrate != NULL);
    DEVICE_ASSERT(bitrate->SEG_2 <= CAN_MAX_S_SEG_2);
    DEVICE_ASSERT(bitrate->SJW <= CAN_MAX_S_SJW);
    /* PRQA S 0311 ++ */
    base->SBITRATE = *(uint32_t *)bitrate;
    /* PRQA S 0311 -- */
}

/*!
 * @brief Get CAN normal slow bitrate.
 *
 * @param[in] base: CAN module
 * @param[in] bitrate: pointer to bitrate configuration
 * @return none
 */
static inline void CAN_GetSlowBitrate(CAN_Type *base, can_time_segment_t *bitrate)
{
    DEVICE_ASSERT(bitrate != NULL);

    bitrate->SEG_1 = (uint8_t)((base->SBITRATE & CAN_SBITRATE_S_SEG_1_Msk) >> CAN_SBITRATE_S_SEG_1_Pos);
    bitrate->SEG_2 = (uint8_t)((base->SBITRATE & CAN_SBITRATE_S_SEG_2_Msk) >> CAN_SBITRATE_S_SEG_2_Pos);
    bitrate->SJW =   (uint8_t)((base->SBITRATE & CAN_SBITRATE_S_SJW_Msk) >> CAN_SBITRATE_S_SJW_Pos);
    bitrate->PRESC = (uint8_t)((base->SBITRATE & CAN_SBITRATE_S_PRESC_Msk) >> CAN_SBITRATE_S_PRESC_Pos);
}

/*!
 * @brief Set CAN FD data bitrate.
 *
 * @param[in] base: CAN module
 * @param[in] bitrate: pointer to bitrate configuration
 * @return none
 */
static inline void CAN_SetFastBitrate(CAN_Type *base, const can_time_segment_t *bitrate)
{
    DEVICE_ASSERT(bitrate != NULL);
    DEVICE_ASSERT(bitrate->SEG_1 <= CAN_MAX_F_SEG_1);
    DEVICE_ASSERT(bitrate->SEG_2 <= CAN_MAX_F_SEG_2);
    DEVICE_ASSERT(bitrate->SJW <= CAN_MAX_F_SJW);
    /* PRQA S 0311 ++ */
    base->FBITRATE = *(uint32_t *)bitrate;
    /* PRQA S 0311 -- */
}

/*!
 * @brief Get CAN FD data bitrate.
 *
 * @param[in] base: CAN module
 * @param[in] bitrate: pointer to bitrate configuration
 * @return none
 */
static inline void CAN_GetFastBitrate(CAN_Type *base, can_time_segment_t *bitrate)
{
    DEVICE_ASSERT(bitrate != NULL);

    bitrate->SEG_1 = (uint8_t)((base->FBITRATE & CAN_FBITRATE_F_SEG_1_Msk) >> CAN_FBITRATE_F_SEG_1_Pos);
    bitrate->SEG_2 = (uint8_t)((base->FBITRATE & CAN_FBITRATE_F_SEG_2_Msk) >> CAN_FBITRATE_F_SEG_2_Pos);
    bitrate->SJW =   (uint8_t)((base->FBITRATE & CAN_FBITRATE_F_SJW_Msk) >> CAN_FBITRATE_F_SJW_Pos);
    bitrate->PRESC = (uint8_t)((base->FBITRATE & CAN_FBITRATE_F_PRESC_Msk) >> CAN_FBITRATE_F_PRESC_Pos);
}

/*!
 * @brief Get arbitration lost capture.
 *
 * @param[in] base: CAN module
 * @return Arbitration lost capture position
 */
static inline uint8_t CAN_GetArbitLostCap(CAN_Type *base)
{
    return (uint8_t)((base->ERRINFO & CAN_ERRINFO_ALC_Msk) >> CAN_ERRINFO_ALC_Pos);
}

/*!
 * @brief Get kind of bus error.
 *
 * @param[in] base: CAN module
 * @return Kind of bus error
 */
static inline uint8_t CAN_GetKoer(CAN_Type *base)
{
    return (uint8_t)((base->ERRINFO & CAN_ERRINFO_KOER_Msk) >> CAN_ERRINFO_KOER_Pos);
}

/*!
 * @brief Set SSP offset.
 *
 * @param[in] base: CAN module
 * @param[in] offset: SSP offset (1-0x7f)
 * @return none
 */
static inline void CAN_SetSspOffset(CAN_Type *base, uint8_t offset)
{
    MODIFY_REG32(base->ERRINFO, CAN_ERRINFO_SSPOFF_Msk, CAN_ERRINFO_SSPOFF_Pos, offset);
}

/*!
 * @brief Set TDC enable.
 *
 * @param[in] base: CAN module
 * @param[in] enable: TDC enable state
 * @return none
 */
static inline void CAN_SetTdc(CAN_Type *base, bool enable)
{
    MODIFY_REG32(base->ERRINFO, CAN_ERRINFO_TDCEN_Msk, CAN_ERRINFO_TDCEN_Pos, enable);
}

/*!
 * @brief Get receive error count.
 *
 * @param[in] base: CAN module
 * @return Receive error count
 */
static inline uint8_t CAN_GetReCount(CAN_Type *base)
{
    return (uint8_t)((base->ERRINFO & CAN_ERRINFO_RECNT_Msk) >> CAN_ERRINFO_RECNT_Pos);
}

/*!
 * @brief Get transmit error count.
 *
 * @param[in] base: CAN module
 * @return Transmit error count
 */
static inline uint8_t CAN_GetTeCount(CAN_Type *base)
{
    return (uint8_t)((base->ERRINFO & CAN_ERRINFO_TECNT_Msk) >> CAN_ERRINFO_TECNT_Pos);
}

/*!
 * @brief Set time stamp enable.
 *
 * @param[in] base: CAN module
 * @param[in] enable: time stamp enable state
 * @return none
 */
static inline void CAN_SetTimeStamp(CAN_Type *base, bool enable)
{
    MODIFY_REG32(base->ACFCTRL0, CAN_ACFCTRL0_TIMEEN_Msk, CAN_ACFCTRL0_TIMEEN_Pos, enable);
}

/*!
 * @brief Set time stamp position.
 *
 * @param[in] base: CAN module
 * @param[in] pos: time stamp position
 *              - CAN_TIME_STAMP_SOF
 *              - CAN_TIME_STAMP_EOF
 * @return none
 */
static inline void CAN_SetTimeStampPos(CAN_Type *base, can_time_stamp_pos_t pos)
{
    MODIFY_REG32(base->ACFCTRL0, CAN_ACFCTRL0_TIMEPOS_Msk, CAN_ACFCTRL0_TIMEPOS_Pos, (uint32_t)pos);
}

/*!
 * @brief Set time stamp counter enable.
 *
 * @param[in] base: CAN module
 * @param[in] enable: time stamp counter enable state
 * @return none
 */
static inline void CAN_SetTimeStampCount(CAN_Type *base, bool enable)
{
    MODIFY_REG32(base->ACFCTRL0, CAN_ACFCTRL0_TCEN_Msk, CAN_ACFCTRL0_TCEN_Pos, enable);
}

/*!
 * @brief Set time stamp clock source.
 *
 * @param[in] base: CAN module
 * @param[in] src: time stamp clock source
 *              - CAN_TIME_STAMP_CLK_SRC_EXT
 *              - CAN_TIME_STAMP_CLK_SRC_BIT
 * @return none
 */
static inline void CAN_SetTimeStampClkSrc(CAN_Type *base, can_time_stamp_clk_src_t src)
{
    MODIFY_REG32(base->ACFCTRL0, CAN_ACFCTRL0_TCSS_Msk, CAN_ACFCTRL0_TCSS_Pos, (uint32_t)src);
}

/*!
 * @brief Set acceptance filter index.
 *
 * @param[in] base: CAN module
 * @param[in] index: filter index
 * @return none
 */
static inline void CAN_SetAcfIndex(CAN_Type *base, uint8_t index)
{
    DEVICE_ASSERT(index < CAN_FILTER_NUM_MAX);

    MODIFY_REG32(base->ACFCTRL0, CAN_ACFCTRL0_ACFADR_Msk, CAN_ACFCTRL0_ACFADR_Pos, index);
}

/*!
 * @brief Set filter data code.
 *
 * @param[in] base: CAN module
 * @param[in] code: filter data code
 * @return none
 */
static inline void CAN_SetAcfCode(CAN_Type *base, uint32_t code)
{
    base->ACFCTRL0 &= (~CAN_ACFCTRL0_SELMASK_Msk);
    base->ACF = (code & CAN_ACF_ACODE_Msk);
}

/*!
 * @brief Set filter data mask + AIDE + AIDEE.
 *
 * @param[in] base: CAN module
 * @param[in] mask: filter data mask + AIDE + AIDEE
 * @return none
 */
static inline void CAN_SetAcfMask(CAN_Type *base, uint32_t mask)
{
    base->ACFCTRL0 |= CAN_ACFCTRL0_SELMASK_Msk;
    base->ACF = mask & (CAN_ACF_ACODE_Msk | CAN_ACF_AIDE_Msk | CAN_ACF_AIDEE_Msk);
}

/*!
 * @brief Set VERMEM register.
 *
 * @param[in] base: CAN module
 * @param[in] value: VERMEM register value
 * @return none
 */
static inline void CAN_SetVerMem(CAN_Type *base, uint32_t value)
{
    base->VERMEM = value;
}

/*!
 * @brief Get VERMEM register.
 *
 * @param[in] base: CAN module
 * @return VERMEM register value
 */
static inline uint32_t CAN_GetVerMem(CAN_Type *base)
{
    return base->VERMEM;
}

/*!
 * @brief Get CAN version.
 *
 * @param[in] base: CAN module
 * @return CAN version
 */
static inline uint32_t CAN_GetVersion(CAN_Type *base)
{
    return (base->VERMEM & CAN_VERMEM_VERSION_Msk);
}

/*!
 * @brief Set memory ECC protect enable.
 *
 * @param[in] base: CAN module
 * @param[in] enable: ECC protect enable state
 * @return none
 */
static inline void CAN_SetMemEcc(CAN_Type *base, bool enable)
{
    MODIFY_REG32(base->VERMEM, CAN_VERMEM_MEEN_Msk, CAN_VERMEM_MEEN_Pos, enable);
}

/*!
 * @brief Get memory ECC protect enable state.
 *
 * @param[in] base: CAN module
 * @return ECC protect enable state
 */
static inline bool CAN_GetEccState(CAN_Type *base)
{
    return (((base->VERMEM & CAN_VERMEM_MEEN_Msk) >> CAN_VERMEM_MEEN_Pos) != 0U);
}

/*!
 * @brief Set memory ECC interrupt enable mask.
 *
 * @param[in] base: CAN module
 * @param[in] IntMask: ECC interrupt enable mask
 * @return none
 */
static inline void CAN_SetEccIntMask(CAN_Type *base, uint32_t IntMask)
{
    MODIFY_REG32(base->VERMEM, (CAN_VERMEM_MDWIE_Msk | CAN_VERMEM_MDEIE_Msk), 0, IntMask);
}

/*!
 * @brief Check memory ECC is initialized done.
 *
 * @param[in] base: CAN module
 * @return CAN memory initialization status
 */
static inline bool CAN_IsMemInitDone(CAN_Type *base)
{
    return (((base->VERMEM & CAN_VERMEM_MEID_Msk) >> CAN_VERMEM_MEID_Pos) != 0U);
}

/*!
 * @brief Get memory ECC error status.
 *
 * @param[in] base: CAN module
 * @return ECC error status
 */
static inline uint8_t CAN_GetEccStatus(CAN_Type *base)
{
    return (uint8_t)((base->VERMEM & (CAN_VERMEM_ACFA_Msk | CAN_VERMEM_TXS_Msk | \
        CAN_VERMEM_HELOC_Msk)) >> CAN_VERMEM_ACFA_Pos);
}

/*!
 * @brief Set memory error bit position 1.
 *
 * @param[in] base: CAN module
 * @param[in] position: memory error bit postion 1
 * @return none
 */
static inline void CAN_SetMebp1(CAN_Type *base, uint8_t position)
{
    MODIFY_REG32(base->MEMES, CAN_MEMES_MEBP1_Msk, CAN_MEMES_MEBP1_Pos, position);
}

/*!
 * @brief Set memory 1st error enable.
 *
 * @param[in] base: CAN module
 * @param[in] enable: memory 1st error enable state
 * @return none
 */
static inline void CAN_SetMe1ee(CAN_Type *base, bool enable)
{
    MODIFY_REG32(base->MEMES, CAN_MEMES_ME1EE_Msk, CAN_MEMES_ME1EE_Pos, enable);
}

/*!
 * @brief Set memory error bit position 2.
 *
 * @param[in] base: CAN module
 * @param[in] position: memory error bit postion 2
 * @return none
 */
static inline void CAN_SetMebp2(CAN_Type *base, uint8_t position)
{
    MODIFY_REG32(base->MEMES, CAN_MEMES_MEBP2_Msk, CAN_MEMES_MEBP2_Pos, position);
}

/*!
 * @brief Set memory 2nd error enable.
 *
 * @param[in] base: CAN module
 * @param[in] enable: memory 2nd error enable state
 * @return none
 */
static inline void CAN_SetMe2ee(CAN_Type *base, bool enable)
{
    MODIFY_REG32(base->MEMES, CAN_MEMES_ME2EE_Msk, CAN_MEMES_ME2EE_Pos, enable);
}

/*!
 * @brief Set memory error counter.
 *
 * @param[in] base: CAN module
 * @param[in] count: memory error counter
 * @return none
 */
static inline void CAN_SetMeeec(CAN_Type *base, uint8_t count)
{
    MODIFY_REG32(base->MEMES, CAN_MEMES_MEEEC_Msk, CAN_MEMES_MEEEC_Pos, count);
}

/*!
 * @brief Set memory no error counter.
 *
 * @param[in] base: CAN module
 * @param[in] count: memory no error counter
 * @return none
 */
static inline void CAN_SetMenec(CAN_Type *base, uint8_t count)
{
    MODIFY_REG32(base->MEMES, CAN_MEMES_MENEC_Msk, CAN_MEMES_MENEC_Pos, count);
}

/*!
 * @brief Set memory error location.
 *
 * @param[in] base: CAN module
 * @param[in] location: memory error location
 * @return none
 */
static inline void CAN_SetMel(CAN_Type *base, uint8_t location)
{
    MODIFY_REG32(base->MEMES, CAN_MEMES_MEL_Msk, CAN_MEMES_MEL_Pos, location);
}

/*!
 * @brief Set memory error side.
 *
 * @param[in] base: CAN module
 * @param[in] side: memory error side
 * @return none
 */
static inline void CAN_SetMes(CAN_Type *base, uint8_t side)
{
    MODIFY_REG32(base->MEMES, CAN_MEMES_MES_Msk, CAN_MEMES_MES_Pos, side);
}

/*!
 * @brief Set low pass filter enable for low power mode.
 *
 * @param[in] base: CAN module
 * @param[in] enable: low pass filter enable state
 * @return none
 */
static inline void CAN_SetLowPassFilter(CAN_Type *base, bool enable)
{
    MODIFY_REG32(base->WAKEUP, CAN_WAKEUP_LPFEN_Msk, CAN_WAKEUP_LPFEN_Pos, enable);
}

/*!
 * @brief Set wakeup enable for low power mode.
 *
 * @param[in] base: CAN module
 * @param[in] enable: wakeup enable state
 * @return none
 */
static inline void CAN_SetWakeup(CAN_Type *base, bool enable)
{
    MODIFY_REG32(base->WAKEUP, CAN_WAKEUP_WUEN_Msk, CAN_WAKEUP_WUEN_Pos, enable);
}

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* CAN_HW_H */

/* =============================================  EOF  ============================================== */
