/*******************************************************************************
 * DISCLAIMER
 * This software is supplied by Renesas Electronics Corporation and is only
 * intended for use with Renesas products. No other uses are authorized. This
 * software is owned by Renesas Electronics Corporation and is protected under
 * all applicable laws, including copyright laws.
 * THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
 * THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT
 * LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.
 * TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS
 * ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE
 * FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR
 * ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE
 * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 * Renesas reserves the right, without notice, to make changes to this software
 * and to discontinue the availability of this software. By using this software,
 * you agree to the additional terms and conditions found by accessing the
 * following link:
 * http://www.renesas.com/disclaimer
 *
 * Copyright (C) 2013 Renesas Electronics Corporation. All rights reserved.
 *******************************************************************************/
/*******************************************************************************
 * File Name    : r_rl78_can_drv.c
 * Version      : 1.0
 * Description  : This is source file for CAN driver code.
 ******************************************************************************/
/*****************************************************************************
 * History      : DD.MM.YYYY Version Description
 *              : 29.03.2013 1.00     First Release
 ******************************************************************************/

/*****************************************************************************
 Includes   <System Includes> , "Project Includes"
 *****************************************************************************/
#include "r_cg_macrodriver.h"
#include "r_rl78_can_drv.h"
#include "r_rl78_can_sfr.h"
#include "RL78_RCAN.h"

/*****************************************************************************
 Typedef definitions
 *****************************************************************************/

/*****************************************************************************
 Macro definitions
 *****************************************************************************/

#define CAN_FIFO_PTR_INC 0xffUL

#define CAN_8_BITS_MASK 0x00FFU

/*****************************************************************************
 Private variables and functions
 *****************************************************************************/

/*****************************************************************************
 Exported global variables and functions (to be accessed by other files)
 *****************************************************************************/

/******************************************************************************
 * Function Name: R_Can_Init
 * Description  : Initialize CAN controller after reset
 * Arguments    : none
 * Return Value : CAN_RTN_OK -
 *                    normal completion
 *                CAN_RTN_RAM_INIT -
 *                    CAN RAM initializing
 *                CAN_RTN_MODE_WAIT -
 *                    wait to change global mode or channel mode
 ******************************************************************************/
volatile can_rxrule_sfr_t *p_RxRuleSfr; //
Can_RtnType R_CAN_Init(void)
{

    /* ==== CAN RAM initialization ==== */
    if ((GSTS & CAN_RAM_INIT_BIT_ON) != 0U) /*GSTS&0x80, waiting CAN RAM initialization completed*/
    {
        return CAN_RTN_RAM_INIT; /* return 05U */
    }

    /* ==== global mode switch (stop->reset) ==== */
    if ((GSTS & CAN_GLB_STP_STS_BIT_ON) != 0U) /*GSTS&0x04, judgment global in stop mode*/
    {
        /* exit global stop mode */
        GCTRL &= (uint16_t) ~(CAN_GLB_STP_BIT_ON); /* not in global stop mode*/
        if ((GSTS & CAN_GLB_STP_STS_BIT_ON) != 0U) /*if still in stop mode*/
        {
            return CAN_RTN_MODE_WAIT; /* return 04u*/
        }
    }

    /* ==== channel mode switch ==== */
    /* --- switch from channel stop mode ---- */
    if ((C0STSL & CAN_STP_STS_BIT_ON) != 0U) /* C0STSL & 0x04; judgment in channel stop mode*/
    {
        /* exit channel stop mode */
        C0CTRL &= (uint16_t) ~(CAN_STP_BIT_ON); /* C0STSL & 0xFB; not in stop mode*/
        if ((C0STSL & CAN_STP_STS_BIT_ON) != 0U)
        {
            return CAN_RTN_MODE_WAIT; /* return 04u*/
        }
    }

    /* ==== global function setting ==== */
    GCFGL = CAN_CFG_GLB_CFGL; /*ID priority, DLC check is disable, DLC replacment is disable
                                Mirror function is disabled, clock obtained by frequency-dividing Fclk by 2*/
    GCFGH = CAN_CFG_GLB_CFGH; /*0x0000*/
    // fcl/2--32M/2--16M
    /* ==== communication speed setting: 500K ==== 16M/2/(11+4+1)=500K*/
    // C0CFGL = CAN_CFG_C0_BAUDRATE_L;   /*0x0001 Prescaler:2 */
    C0CFGL = 0x1; // 500K
    // C0CFGL = 0x3; //250K
    C0CFGH = CAN_CFG_C0_BAUDRATE_H; /*CAN_TSEG1_11TQ, CAN_TSEG2_4TQ, CAN_SJW_2TQ*/
                                    // C0CFGH = 0x022B;  //TSEG1:0B,TSEG2:02,sample point=(12+1)/(12+3+1)=81.25%
    /* ==== Rx rule setting ==== */
#if CAN_RX_RULE_NUM > 0
    {
        // volatile  can_rxrule_sfr_t * p_RxRuleSfr; //
        uint16_t temp_rpage;
        uint16_t rxrule_idx;

        /* ---- Set Rx rule number per channel ---- */
        GAFLCFG = CAN_CFG_RN0; /*CAN_CFG_RN0=0x04*/

        /* ---- Save value of GRWCR register ---- */
        temp_rpage = GRWCR;

        /* ---- Select window 0 ---- */
        GRWCR &= (uint16_t) ~(CAN_RAM_WINDOW_BIT_ON); /*Setting GRWCR=0; Select window 0*/

        /* ---- Copy Rx rule one by one ---- */ ///////////////////////////////

        p_RxRuleSfr = (volatile can_rxrule_sfr_t *)&GAFLIDL0; //__near

        for (rxrule_idx = 0U; rxrule_idx < CAN_RX_RULE_NUM; rxrule_idx++)
        {

            /* Set a single Rx rule */
            p_RxRuleSfr->IDL = g_rxrule_table[rxrule_idx][0];
            p_RxRuleSfr->IDH = g_rxrule_table[rxrule_idx][1];
            p_RxRuleSfr->ML = g_rxrule_table[rxrule_idx][2];
            p_RxRuleSfr->MH = g_rxrule_table[rxrule_idx][3];
            p_RxRuleSfr->PL = g_rxrule_table[rxrule_idx][4];
            p_RxRuleSfr->PH = g_rxrule_table[rxrule_idx][5];

            /* Next sfr */
            p_RxRuleSfr++;
        }

        /* ---- restore value of GRWCR register ---- */
        GRWCR = temp_rpage;
    }
#endif /* CAN_RX_RULE_NUM > 0 */

    /* ==== buffer setting ==== */
    /* ---- Set Rx buffer number ---- */
    RMNB = CAN_CFG_RBNUM;

    /* ---- Set Rx FIFO buffer ---- */
    RFCC0 = CAN_CFG_RXFIFO0;
    RFCC1 = CAN_CFG_RXFIFO1;

    /* ---- Set common (Tx/Rx) FIFO buffer ---- */
    CFCCL0 = CAN_CFG_C0_TRFIFO0_L;
    CFCCH0 = CAN_CFG_C0_TRFIFO0_H;

    /* ---- Tx buffer transmission complete interrupt ---- */
    TMIEC = CAN_CFG_C0_TXBUF_IE;

    /* ==== global error interrupt setting ==== */
    GCTRL = (GCTRL & (CAN_GLB_STP_BIT_ON | CAN_GLB_MODE_BITS_ON)) + CAN_CFG_GLB_ERR_INT;

    /* ==== channel function setting ==== */
    C0CTRL = (C0CTRL & (CAN_STP_BIT_ON | CAN_MODE_BITS_ON)) + CAN_CFG_C0_FUNC_L;
    //C0CTRLL = 0x02;
    C0CTRH = C0CTRH + CAN_CFG_C0_FUNC_H;
    //C0CTRH |= 0x300;

    enable_interrupt_request_mask();

    return CAN_RTN_OK;
}

/******************************************************************************
 * Function Name: R_CAN_GlobalStart
 * Description  : Start global operation
 * Arguments    : none
 * Return Value : CAN_RTN_OK -
 *                    normal completion
 *                CAN_RTN_MODE_WAIT -
 *                    wait to change global mode
 ******************************************************************************/
Can_RtnType R_CAN_GlobalStart(void)
{

    /* ==== switch to global operation mode from global reset mode ==== */
    if ((GSTS & CAN_GLB_RST_STS_BIT_ON) != 0U) /*in global reset mode*/
    {
        GCTRL = ((GCTRL & (uint16_t)~CAN_GLB_MODE_BITS_ON) |
                 CAN_GLB_OPERATION_MODE);
        if ((GSTS & CAN_GLB_RST_STS_BIT_ON) != 0U)
        {
            return CAN_RTN_MODE_WAIT;
        }
    }

    /* ==== Global error ==== */
    GERFLL = 0x0U; /*clear DLC error flag*/

    /* ==== enable reception FIFO ==== */
    if (g_rxfifo0_use_mode != CAN_NOUSE)
    {
        RFCC0 |= CAN_RFIFO_EN_BIT_ON;
    }

    if (g_rxfifo1_use_mode != CAN_NOUSE)
    {
        RFCC1 |= CAN_RFIFO_EN_BIT_ON;
    }

    /* ==== Tx/Rx FIFO setting ==== */
    /* ---- enable Tx/Rx FIFO (Rx mode) ---- */
    if (g_trfifo_use_mode == CAN_USE_RX_MODE)
    {
        CFCCL0 |= CAN_TRFIFO_EN_BIT_ON;
    }

    return CAN_RTN_OK;
}

/******************************************************************************
 * Function Name: R_CAN_ChStart_CH0
 * Description  : Start channel operation (Channel 0)
 * Arguments    : none
 * Return Value : CAN_RTN_OK -
 *                    normal completion
 *                CAN_RTN_MODE_WAIT -
 *                    wait to change channel mode
 ******************************************************************************/
Can_RtnType R_CAN_ChStart_CH0(void)
{
    /* ---- switch to channel operation mode ---- */
    if ((C0STSL & CAN_RST_STS_BIT_ON) != 0U)
    {
        C0CTRL = (C0CTRL & (uint16_t)~CAN_MODE_BITS_ON) | CAN_MODE_CH_COMM_MODE;
        if ((C0STSL & CAN_RST_STS_BIT_ON) != 0U)
        {
            return CAN_RTN_MODE_WAIT;
        }
    }

    /* ---- enable Tx/Rx FIFO (Tx mode) ---- */
    if (g_trfifo_use_mode == CAN_USE_TX_MODE)
    {
        CFCCL0 |= CAN_TRFIFO_EN_BIT_ON;
    }

    return CAN_RTN_OK;
}

/******************************************************************************
 * Function Name: R_CAN_TrmByTxBuf_CH0
 * Description  : Transmit a frame by Tx buffer (Channel 0)
 * Arguments    : txbuf_idx -
 *                    Tx buffer index
 *                pFrame -
 *                    pointer to frame to be transmitted
 * Return Value : CAN_RTN_OK -
 *                    normal completion
 *                CAN_RTN_STS_ERROR -
 *                    failure to clear Tx buffer status
 *                CAN_RTN_ARG_ERROR -
 *                    invalid argument specification
 ******************************************************************************/
Can_RtnType R_CAN_TrmByTxBuf_CH0(can_txbuf_t txbuf_idx,
                                 const can_frame_t *pFrame)
{
#if defined(__CHECK__)
    /* ----  Check Tx buffer index ---- */
    if (txbuf_idx >= CAN_MAX_TXBUF_NUM)
    {
        return CAN_RTN_ARG_ERROR;
    }
#endif

    /* ---- Clear Tx buffer status ---- */
    {
        volatile uint8_t *p_TMSTSp; //__near

        p_TMSTSp = CAN_ADDR_TMSTSp(txbuf_idx);
        *p_TMSTSp = 0x0U;
        if (*p_TMSTSp != 0x0U)
        {
            return CAN_RTN_STS_ERROR;
        }
    }

    /* ---- Store message to tx buffer ---- */
    {
        volatile can_frame_sfr_t *p_TxMsgSfr; // __near
        uint16_t temp_rpage;

        /* ---- Save value of GRWCR register ---- */
        temp_rpage = GRWCR;

        /* ---- Select window 1 ---- */
        GRWCR |= CAN_RAM_WINDOW_BIT_ON;

        /* ---- Set frame data ---- */
        p_TxMsgSfr = CAN_ADDR_TMIDLp(txbuf_idx);
        p_TxMsgSfr->IDL = ((can_frame_sfr_t *)pFrame)->IDL;
        p_TxMsgSfr->IDH = ((can_frame_sfr_t *)pFrame)->IDH;
        p_TxMsgSfr->PTR = ((can_frame_sfr_t *)pFrame)->PTR;
        p_TxMsgSfr->DF0 = ((can_frame_sfr_t *)pFrame)->DF0;
        p_TxMsgSfr->DF1 = ((can_frame_sfr_t *)pFrame)->DF1;
        p_TxMsgSfr->DF2 = ((can_frame_sfr_t *)pFrame)->DF2;
        p_TxMsgSfr->DF3 = ((can_frame_sfr_t *)pFrame)->DF3;

        /* ---- Restore value of GRWCR register ---- */
        GRWCR = temp_rpage;
    }

    /* ---- Set transmission request ---- */
    TMCp(txbuf_idx) = CAN_TXBUF_TRM_BIT_ON;

    return CAN_RTN_OK;
}

/******************************************************************************
 * Function Name: R_CAN_AbortTrm_CH0
 * Description  : Abort a CAN transmission (Channel 0)
 * Arguments    : txbuf_idx -
 *                    Tx buffer index
 * Return Value : CAN_RTN_OK -
 *                    normal completion
 *                CAN_RTN_ARG_ERROR -
 *                    invalid argument specification
 ******************************************************************************/
Can_RtnType R_CAN_AbortTrm_CH0(can_txbuf_t txbuf_idx)
{
#if defined(__CHECK__)
    /* ----  Check Tx buffer index ---- */
    if (txbuf_idx >= CAN_MAX_TXBUF_NUM)
    {
        return CAN_RTN_ARG_ERROR;
    }
#endif

    /* ---- Set transmission abort request ---- */
    TMCp(txbuf_idx) |= CAN_TXBUF_ABT_BIT_ON;

    return CAN_RTN_OK;
}

/******************************************************************************
 * Function Name: R_CAN_CheckTxBufResult_CH0
 * Description  : Read the result of transmission from Tx buffer (Channel 0)
 * Arguments    : txbuf_idx -
 *                    Tx buffer index
 * Return Value : CAN_RTN_TRANSMITTING -
 *                    Transmission is in progress
 *                    or no transmit request is present.
 *                CAN_RTN_TX_ABORT_OVER -
 *                    Transmit abort has been completed.
 *                CAN_RTN_TX_END -
 *                    Transmission has been completed
 *                    (without transmit abort request).
 *                CAN_RTN_TX_END_WITH_ABORT_REQ -
 *                    Transmission has been completed
 *                    (with transmit abort request).
 *                CAN_RTN_ARG_ERROR -
 *                    invalid argument specification
 ******************************************************************************/
Can_RtnType R_CAN_CheckTxBufResult_CH0(can_txbuf_t txbuf_idx)
{
    Can_RtnType rtn_value;

    volatile uint8_t *p_TMSTSp; //__near

#if defined(__CHECK__)
    /* ----  Check Tx buffer index ---- */
    if (txbuf_idx >= CAN_MAX_TXBUF_NUM)
    {
        return CAN_RTN_ARG_ERROR;
    }
#endif

    p_TMSTSp = CAN_ADDR_TMSTSp(txbuf_idx);

    rtn_value = (Can_RtnType)((*p_TMSTSp & CAN_TXBUF_RSLT_BITS_ON) >> CAN_TXBUF_RSLT_BITS_POS);

    /* ---- Tx transmission completed/abort? ---- */
    if (rtn_value != CAN_RTN_TRANSMITTING)
    {
        /* Clear Tx buffer status */
        *p_TMSTSp = 0x0U;
    }

    return rtn_value;
}

/******************************************************************************
 * Function Name: R_CAN_TrmByTRFIFO0_CH0
 * Description  : Transmit a frame by common (Tx/Rx) FIFO 0 (Channel 0)
 * Arguments    : ch_idx -
 *                    channel index
 *                trfifo_idx -
 *                    Tx/Rx FIFO index
 *                pFrame -
 *                    pointer to frame to be transmitted
 * Return Value : CAN_RTN_OK -
 *                    Frame is successfully pushed into FIFO.
 *                CAN_RTN_FIFO_FULL -
 *                    Specified FIFO is full.
 *                CAN_RTN_ARG_ERROR -
 *                    invalid argument specification
 ******************************************************************************/
Can_RtnType R_CAN_TrmByTRFIFO0_CH0(const can_frame_t *pFrame)
{
#if defined(__CHECK__)
    /* ----  Check Tx/Rx FIFO 0 mode ---- */
    if (g_trfifo_use_mode != CAN_USE_TX_MODE)
    {
        return CAN_RTN_ARG_ERROR;
    }
#endif

    /* ---- Return if Tx/Rx FIFO is full ---- */
    if ((CFSTS0 & CAN_TRFIFO_FULL_BIT_ON) != 0)
    {
        return CAN_RTN_FIFO_FULL;
    }

    /* ---- Send message into Tx/Rx FIFO if it is not full ---- */
    {
        uint16_t temp_rpage;

        /* ---- save value of GRWCR register ---- */
        temp_rpage = GRWCR;

        /* ---- Select window 1 ---- */
        GRWCR |= CAN_RAM_WINDOW_BIT_ON;

        /* ---- Set frame data ---- */
        CFIDL0 = ((can_frame_sfr_t *)pFrame)->IDL;
        CFIDH0 = ((can_frame_sfr_t *)pFrame)->IDH;
        CFPTR0 = ((can_frame_sfr_t *)pFrame)->PTR;
        CFDF00 = ((can_frame_sfr_t *)pFrame)->DF0;
        CFDF10 = ((can_frame_sfr_t *)pFrame)->DF1;
        CFDF20 = ((can_frame_sfr_t *)pFrame)->DF2;
        CFDF30 = ((can_frame_sfr_t *)pFrame)->DF3;

        /* ---- restore value of GRWCR register ---- */
        GRWCR = temp_rpage;
    }

    /* ---- Increment Tx/Rx FIFO buffer pointer ---- */
    CFPCTR0 = CAN_FIFO_PTR_INC;

    return CAN_RTN_OK;
}

/******************************************************************************
 * Function Name: R_CAN_ReadRxBuffer
 * Description  : Read message from Rx buffer
 * Arguments    : p_rxbuf_idx -
 *                    pointer to Rx buffer that receives frame
 *                pFrame -
 *                    pointer to stored frame position
 * Return Value : CAN_RTN_OK -
 *                    A frame is successfully read out.
 *                CAN_RTN_BUFFER_EMPTY -
 *                    No frame is read out.
 *                CAN_RTN_STS_ERROR -
 *                    failure to clear Rx complete flag
 *                CAN_RTN_OVERWRITE -
 *                    A frame is overwritten.
 ******************************************************************************/
Can_RtnType R_CAN_ReadRxBuffer(uint8_t *p_rxbuf_idx, can_frame_t *pFrame)
{
    uint8_t buf_idx;
    uint16_t temp_rbrcf;
    uint16_t pattern;

    /* ---- Judge if new messages are available ---- */
    temp_rbrcf = RMND0;
    if (temp_rbrcf == 0)
    {
        return CAN_RTN_BUFFER_EMPTY;
    }

    /* ---- Get Rx buffer that has new message ---- */
    if (temp_rbrcf != 0)
    {
        pattern = 1;
        for (buf_idx = 0U; buf_idx < 16U; ++buf_idx)
        {
            if ((temp_rbrcf & pattern) != 0)
            {
                *p_rxbuf_idx = buf_idx;
                break;
            }
            pattern <<= 1;
        }
    }

    /* ---- Clear Rx complete flag of corresponding Rx buffer ---- */
    RMND0 &= (uint16_t)~pattern;
    if ((RMND0 & pattern) != 0)
    {
        return CAN_RTN_STS_ERROR;
    }

    /* ---- Read out message from Rx buffer ---- */
    {
        volatile can_frame_sfr_t *p_RxBufSfr; // __near
        uint16_t temp_rpage;

        /* ---- Save value of GRWCR register ---- */
        temp_rpage = GRWCR;

        /* ---- Select window 1 ---- */
        GRWCR |= CAN_RAM_WINDOW_BIT_ON;

        /* ---- Read frame data ---- */
        p_RxBufSfr = CAN_ADDR_RMIDLp(*p_rxbuf_idx);
        ((can_frame_sfr_t *)pFrame)->IDL = p_RxBufSfr->IDL;
        ((can_frame_sfr_t *)pFrame)->IDH = p_RxBufSfr->IDH;
        ((can_frame_sfr_t *)pFrame)->TS = p_RxBufSfr->TS;
        ((can_frame_sfr_t *)pFrame)->PTR = p_RxBufSfr->PTR;
        ((can_frame_sfr_t *)pFrame)->DF0 = p_RxBufSfr->DF0;
        ((can_frame_sfr_t *)pFrame)->DF1 = p_RxBufSfr->DF1;
        ((can_frame_sfr_t *)pFrame)->DF2 = p_RxBufSfr->DF2;
        ((can_frame_sfr_t *)pFrame)->DF3 = p_RxBufSfr->DF3;

        /* ---- restore value of GRWCR register ---- */
        GRWCR = temp_rpage;
    }

    /* ---- Judge if current message is overwritten ---- */
    if ((RMND0 & pattern) != 0)
    {
        return CAN_RTN_OVERWRITE;
    }

    return CAN_RTN_OK;
}

/******************************************************************************
 * Function Name: R_CAN_ReadRxFIFO
 * Description  : Read message from Rx FIFO
 * Arguments    : rxfifo_idx -
 *                    Rx FIFO index
 *                pFrame -
 *                    pointer to stored frame position
 * Return Value : CAN_RTN_OK -
 *                    A frame is successfully read out.
 *                CAN_RTN_OK_WITH_LOST -
 *                    A frame is successfully read out (with message lost).
 *                CAN_RTN_BUFFER_EMPTY -
 *                    No frame is read out.
 *                CAN_RTN_ARG_ERROR -
 *                    invalid argument specification
 ******************************************************************************/
extern Can_RtnType R_CAN_ReadRxFIFO0(can_frame_t *);
extern Can_RtnType R_CAN_ReadRxFIFO1(can_frame_t *);
Can_RtnType R_CAN_ReadRxFIFO(can_rxfifo_t rxfifo_idx, can_frame_t *pFrame)
{
    if (rxfifo_idx == 0)
    {
        return R_CAN_ReadRxFIFO0(pFrame);
    }
    else if (rxfifo_idx == 1)
    {
        return R_CAN_ReadRxFIFO1(pFrame);
#if defined(__CHECK__)
    }

    else
    {
        return CAN_RTN_ARG_ERROR;
#endif
    }

    return CAN_RTN_OK;
}

/******************************************************************************
 * Function Name: R_CAN_ReadRxFIFO0
 * Description  : Read message from Rx FIFO 0
 * Arguments    : pFrame -
 *                    pointer to stored frame position
 * Return Value : CAN_RTN_OK -
 *                    A frame is successfully read out.
 *                CAN_RTN_OK_WITH_LOST -
 *                    A frame is successfully read out (with message lost).
 *                CAN_RTN_BUFFER_EMPTY -
 *                    No frame is read out.
 *                CAN_RTN_ARG_ERROR -
 *                    invalid argument specification
 ******************************************************************************/
Can_RtnType R_CAN_ReadRxFIFO0(can_frame_t *pFrame)
{
    uint16_t temp_status;
    Can_RtnType rtn_value;

#if defined(__CHECK__)
    /* ----  Check Rx FIFO 0 mode ---- */
    if ((g_rxfifo0_use_mode == CAN_NOUSE))
    {
        return CAN_RTN_ARG_ERROR;
    }
#endif

    /* ----  Check if any unread message is available in Rx FIFO ---- */
    temp_status = RFSTS0;
    if ((temp_status & CAN_RFIFO_EMPTY_BIT_ON) != 0)
    {
        return CAN_RTN_BUFFER_EMPTY;
    }

    /* ----  Set return value ---- */
    rtn_value = CAN_RTN_OK;

    /* ---- Check if Rx FIFO has message lost ---- */
    if ((temp_status & CAN_RFIFO_MSGLST_BIT_ON) != 0)
    {
        /* ---- Clear message lost flag ---- */
        RFSTS0 = CAN_CLR_WITHOUT_RX_INT;

        /* ----  Set return value ---- */
        rtn_value = CAN_RTN_OK_WITH_LOST;
    }

    RFSTS0 &= 0xFFF7; /*Clear RFIF  receive FIFO interrupt request flag*/

    /* ---- Read out message from Rx FIFO ---- */
    {
        uint16_t temp_rpage;

        /* ---- Save value of GRWCR register ---- */
        temp_rpage = GRWCR;

        /* ---- Select window 1 ---- */
        GRWCR |= CAN_RAM_WINDOW_BIT_ON;

        /* ---- Read frame data ---- */
        ((can_frame_sfr_t *)pFrame)->IDL = RFIDL0;
        ((can_frame_sfr_t *)pFrame)->IDH = RFIDH0;
        ((can_frame_sfr_t *)pFrame)->TS = RFTS0;
        ((can_frame_sfr_t *)pFrame)->PTR = RFPTR0;
        ((can_frame_sfr_t *)pFrame)->DF0 = RFDF00;
        ((can_frame_sfr_t *)pFrame)->DF1 = RFDF10;
        ((can_frame_sfr_t *)pFrame)->DF2 = RFDF20;
        ((can_frame_sfr_t *)pFrame)->DF3 = RFDF30;

        /* ---- Restore value of GRWCR register ---- */
        GRWCR = temp_rpage;
    }

    /* ---- Increment Rx FIFO buffer pointer ---- */
    RFPCTR0 = CAN_FIFO_PTR_INC;

    return rtn_value;
}

/******************************************************************************
 * Function Name: R_CAN_ReadRxFIFO1
 * Description  : Read message from Rx FIFO 1
 * Arguments    : pFrame -
 *                    pointer to stored frame position
 * Return Value : CAN_RTN_OK -
 *                    A frame is successfully read out.
 *                CAN_RTN_OK_WITH_LOST -
 *                    A frame is successfully read out (with message lost).
 *                CAN_RTN_BUFFER_EMPTY -
 *                    No frame is read out.
 *                CAN_RTN_ARG_ERROR -
 *                    invalid argument specification
 ******************************************************************************/
Can_RtnType R_CAN_ReadRxFIFO1(can_frame_t *pFrame)
{
    uint16_t temp_status;
    Can_RtnType rtn_value;

#if defined(__CHECK__)
    /* ----  Check Rx FIFO 1 mode ---- */
    if ((g_rxfifo1_use_mode == CAN_NOUSE))
    {
        return CAN_RTN_ARG_ERROR;
    }
#endif

    /* ----  Check if any unread message is available in Rx FIFO ---- */
    temp_status = RFSTS1;
    if ((temp_status & CAN_RFIFO_EMPTY_BIT_ON) != 0)
    {
        return CAN_RTN_BUFFER_EMPTY;
    }

    /* ----  Set return value ---- */
    rtn_value = CAN_RTN_OK;

    /* ---- Check if Rx FIFO has message lost ---- */
    if ((temp_status & CAN_RFIFO_MSGLST_BIT_ON) != 0)
    {
        /* ---- Clear message lost flag ---- */
        RFSTS1 = CAN_CLR_WITHOUT_RX_INT;

        /* ----  Set return value ---- */
        rtn_value = CAN_RTN_OK_WITH_LOST;
    }

    RFSTS1 &= ~CAN_CLR_WITHOUT_RX_INT;
    /* ---- Read out message from Rx FIFO ---- */
    {
        uint16_t temp_rpage;

        /* ---- Save value of GRWCR register ---- */
        temp_rpage = GRWCR;

        /* ---- Select window 1 ---- */
        GRWCR |= CAN_RAM_WINDOW_BIT_ON;

        /* ---- Read frame data ---- */
        ((can_frame_sfr_t *)pFrame)->IDL = RFIDL1;
        ((can_frame_sfr_t *)pFrame)->IDH = RFIDH1;
        ((can_frame_sfr_t *)pFrame)->TS = RFTS1;
        ((can_frame_sfr_t *)pFrame)->PTR = RFPTR1;
        ((can_frame_sfr_t *)pFrame)->DF0 = RFDF01;
        ((can_frame_sfr_t *)pFrame)->DF1 = RFDF11;
        ((can_frame_sfr_t *)pFrame)->DF2 = RFDF21;
        ((can_frame_sfr_t *)pFrame)->DF3 = RFDF31;

        /* ---- Restore value of GRWCR register ---- */
        GRWCR = temp_rpage;
    }

    /* ---- Increment Rx FIFO buffer pointer ---- */
    RFPCTR1 = CAN_FIFO_PTR_INC;

    return rtn_value;
}

/******************************************************************************
 * Function Name: R_CAN_ReadTRFIFO
 * Description  : Read message from common (Tx/Rx) FIFO
 * Arguments    : ch_idx -
 *                    channel index
 *                trfifo_idx -
 *                    common (Tx/Rx) FIFO index
 *                pFrame -
 *                    pointer to stored frame position
 * Return Value : CAN_RTN_OK -
 *                    A frame is successfully read out.
 *                CAN_RTN_OK_WITH_LOST -
 *                    A frame is successfully read out (with message lost).
 *                CAN_RTN_BUFFER_EMPTY -
 *                    No frame is read out.
 *                CAN_RTN_ARG_ERROR -
 *                    invalid argument specification
 ******************************************************************************/
Can_RtnType R_CAN_ReadTRFIFO0_CH0(can_frame_t *pFrame)
{
    uint16_t temp_status;
    Can_RtnType rtn_value;

#if defined(__CHECK__)
    /* ----  Check Tx/Rx FIFO 0 mode ---- */
    if (g_trfifo_use_mode != CAN_USE_RX_MODE)
    {
        return CAN_RTN_ARG_ERROR;
    }
#endif

    /* ----  Check if any unread message is available in common (Tx/Rx) FIFO ---- */
    temp_status = CFSTS0;
    if ((temp_status & CAN_TRFIFO_EMPTY_BIT_ON) != 0)
    {
        return CAN_RTN_BUFFER_EMPTY;
    }

    /* ----  Set return value ---- */
    rtn_value = CAN_RTN_OK;

    /* ---- Check if common (Tx/Rx) FIFO has message lost ---- */
    if ((temp_status & CAN_TRFIFO_MSGLST_BIT_ON) != 0)
    {
        /* ---- Clear message lost flag ---- */
        CFSTS0 = CAN_CLR_WITHOUT_TX_RX_INT;

        /* ----  Set return value ---- */
        rtn_value = CAN_RTN_OK_WITH_LOST;
    }

    /* ---- Read out message from common (Tx/Rx) FIFO ---- */
    {
        uint16_t temp_rpage;

        /* ---- Save value of GRWCR register ---- */
        temp_rpage = GRWCR;

        /* ---- Select window 1 ---- */
        GRWCR |= CAN_RAM_WINDOW_BIT_ON;

        /* ---- Read frame data ---- */
        ((can_frame_sfr_t *)pFrame)->IDL = CFIDL0;
        ((can_frame_sfr_t *)pFrame)->IDH = CFIDH0;
        ((can_frame_sfr_t *)pFrame)->TS = CFTS0;
        ((can_frame_sfr_t *)pFrame)->PTR = CFPTR0;
        ((can_frame_sfr_t *)pFrame)->DF0 = CFDF00;
        ((can_frame_sfr_t *)pFrame)->DF1 = CFDF10;
        ((can_frame_sfr_t *)pFrame)->DF2 = CFDF20;
        ((can_frame_sfr_t *)pFrame)->DF3 = CFDF30;

        /* ---- Restore value of GRWCR register ---- */
        GRWCR = temp_rpage;
    }

    /* ---- Increment common (Tx/Rx) FIFO buffer pointer ---- */
    CFPCTR0 = CAN_FIFO_PTR_INC;

    return rtn_value;
}

/******************************************************************************
 * Function Name: R_CAN_ReadChStatus
 * Description  : Read channel status
 * Arguments    : none
 * Return Value : channel status (<= 0xFF) -
 *                    normal completion
 ******************************************************************************/
Can_RtnType R_CAN_ReadChStatus_CH0(void)
{
    return (Can_RtnType)(C0STSL & CAN_8_BITS_MASK);
}
/******************************************************************************
 * Function Name: R_CAN_ReadChStatus
 * Description  : Read channel status
 * Arguments    : none
 * Return Value : channel status (<= 0xFF) -
 *                    normal completion
 ******************************************************************************/
void enable_interrupt_request_mask()
{
    CAN0CFRIF = 0U;
    CAN0WUPIF = 0U;
    CAN0ERRIF = 0U;
    CANGERRIF = 0U;
    CANGRFRIF = 0U;
    CAN0TRMIF = 0U;

    // CAN0CFRMK=0U;
    // CAN0WUPMK=0U;
    CAN0ERRMK = 0U;
    CANGERRMK = 0U;
    CANGRFRMK = 0U;
    CAN0TRMMK = 0U;
}

void CanUserInit(void)
{
    Can_RtnType retval;

    CAN0EN = 0;
    NOP();
    /* supply CAN clock */
    CAN0EN = 1;

    /* CAN Initialize */
    retval = CAN_RTN_RAM_INIT; // CAN_RTN_RAM_INIT=5U
    while (retval != CAN_RTN_OK)
    {
        retval = R_CAN_Init();
    }

    /* Set global operating mode */
    retval = CAN_RTN_MODE_WAIT;
    while (retval == CAN_RTN_MODE_WAIT)
    {
        retval = R_CAN_GlobalStart();
    }

    /* CH0 -> Channel communication mode */
    retval = CAN_RTN_MODE_WAIT;
    while (retval == CAN_RTN_MODE_WAIT)
    {
        retval = R_CAN_ChStart(CAN_CH0);
    }
}
