
/** @file mcp_can.c
 *
 * @brief  CAN Bus Protocol to send and receive the data.
 *
 * @par
 * NOTICE: Property of in-Terra Limited www.in-terra.ch .
 */

#include "mcp_can.h"
#include "logger_hal.h"
#define TX_RX_MSG_LENGTH 10

// To receive data from the CAN Module after sending the command
uint8_t dummy_receive[];

// CAN Module Parameter Structure like length of data and extended and Normal
// ID

mcp_can_t m_mcp_can;

// NOTE: SPI instance index. Both I2C and SPI Can-Not have same instance index (i.e 0).
//So we are using Instance SPI2 for CAN Communication, also we cannot use 0/spi0 because its already being used by EPAPER


#define SPI_CAN_INSTANCE  2

nrf_drv_spi_t SPI_MASTER_0 = NRF_DRV_SPI_INSTANCE (SPI_CAN_INSTANCE);
static void
spi_master_init (nrf_drv_spi_t spi_master_instance,
    nrf_drv_spi_evt_handler_t spi_master_event_handler);


/**
 * @brief SPI user event handler.
 * @param event
 *
 * @return None
 */

void
spi_master_0_event_handler (nrf_drv_spi_evt_t const *p_event, void *p_context)
{



    if (p_event->type == NRF_DRV_SPI_EVENT_DONE)
        {
            can_xfer_done = true;
            
            
        }
}

/*!
 * @brief     Initilaize the SPI module with pins used and frequency of SPI and
 * Mode of SPI.
 *
 * @param[in] spi_master_instance Instance to be Used.
 * @param[in] nrf_drv_spi_evt_handler_t Event Handler to be used.
 *
 * @return    None.
 */

static void
spi_master_init (nrf_drv_spi_t spi_master_instance,
    nrf_drv_spi_evt_handler_t spi_master_event_handler)
{
    uint32_t err_code = NRF_SUCCESS;
    nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;

    spi_config.ss_pin = NRF_DRV_SPI_PIN_NOT_USED;
    spi_config.miso_pin = LOGGER_MISO;
    spi_config.mosi_pin = LOGGER_MOSI;
    spi_config.sck_pin = LOGGER_SCLK;
    spi_config.frequency = NRF_SPI_FREQ_4M;
    spi_config.mode = NRF_DRV_SPI_MODE_0;
    spi_config.bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST;
    
    APP_ERROR_CHECK (nrf_drv_spi_init (
        &spi_master_instance, &spi_config, spi_master_0_event_handler, NULL));
}

/*!
 * @brief     To send command to CAN Module and Receive the data from it.
 *
 * @param[in] spi_master_instance Instance to be Used.
 * @param[in] p_tx_data Pointer to data/command to be transmitted.
 * @param[in] len_tx    Length of the data to be transmitted.
 * @param[in] p_tx_data Pointer to data to store recived data to.
 * @param[in] len_rx    Length of the data to be recived
 *
 * @return    None.
 */

static void
spi_send_recv (const nrf_drv_spi_t spi_master_hw_instance, uint8_t *p_tx_data,
    uint16_t len_tx, uint8_t *p_rx_data, uint16_t len_rx)
{

    uint8_t *tx_data = p_tx_data;
    uint8_t *rx_data = p_rx_data;
    can_xfer_done = false;
    uint32_t err_code = nrf_drv_spi_transfer (
        &spi_master_hw_instance, tx_data, len_tx, rx_data, len_rx);

    while (!can_xfer_done)
        {

            __WFE ();
        }
    APP_ERROR_CHECK (err_code);
}

/*!
 * @brief     To Select the CS pin of CAN Module
 *
 * @param[in] None
 *
 * @return    None.
 */

void
spi_master_uninit ()
{
    nrf_drv_spi_uninit (&SPI_MASTER_0);
}
/*!
 * @brief     To Select the CS pin of CAN Module
 *
 * @param[in] None
 *
 * @return    None.
 */

void
mcp_select ()
{   
    
    nrf_gpio_pin_clear (CS_CAN);
}

/*!
 * @brief     To UNSELECT/CS PIN HIGH of CAN Module
 *
 * @param[in] None
 *
 * @return    None.
 */

void
mcp_unselect ()
{   
   
    nrf_gpio_pin_set (CS_CAN);
}

/*!
 * @brief     To send reset command so that chip can be configured
 *
 * @param[in] None
 *
 * @return    None.
 */

void
mcp_can_reset ()
{
    // To make initally the CS pin HIGH and then pull LOW.
    mcp_unselect ();

    uint8_t reset_cmd[1];
    reset_cmd[0] = MCP_RESET;

    mcp_select ();
    spi_send_recv (SPI_MASTER_0, &reset_cmd, 1, &dummy_receive, 1);
    SEGGER_RTT_printf (0, "reset can module\r\n");
    mcp_unselect ();
    nrf_delay_ms (10);
}

/*!
 * @brief     To read value of register.
 *
 * @param[in] address of register to read from
 *
 * @return    Acknowldgement data from MCP2515.
 */

uint8_t
mcp2515_readRegister (const uint8_t address)
{
    uint8_t ret;
    uint8_t read_cmd[3] = { MCP_READ, address, 0x00 };
    uint8_t rx_data[3];
    mcp_select ();
    spi_send_recv (SPI_MASTER_0, &read_cmd, 3, &rx_data, 3);
    ret = rx_data[2];
    mcp_unselect ();
    return ret;
}

/*!
 * @brief To send command to CAN Module and Receive the data from it.
 *
 * @param[in] address of register to read from
 * @param[in] array to store the data from read registers
 * @param[in] variable to run the for loop and number of values to be stored in
 * array.
 * @return None
 */

void
mcp2515_readRegisterS (
    const uint8_t address, uint8_t values[], const uint8_t n)
{
    uint8_t i;
    uint8_t read_registers[2] = { MCP_READ, address };
    mcp_select ();
    spi_send_recv (SPI_MASTER_0, &read_registers, 2, &dummy_receive, 2);

    for (i = 0; i < n && i < CAN_MAX_CHAR_IN_MESSAGE; i++)
        {
            spi_send_recv (SPI_MASTER_0, 0x00, 1, &values[i], 1);
        }
    mcp_unselect ();
}

/*!
 * @brief     To write data to a register address
 *
 * @param[in] address of register to write to
 * @param[in] Data to be written/set in register
 * @return    None
 */

void
mcp2515_setRegister (const uint8_t address, const uint8_t value)
{
    mcp_select ();
    uint8_t set_registers[3] = { MCP_WRITE, address, value };
    spi_send_recv (SPI_MASTER_0, &set_registers, 3, &dummy_receive, 3);

    mcp_unselect ();
}

/*!
 * @brief     To write data to a register addresses
 *
 * @param[in] Address of register to write to
 * @param[in] Data to be written/set in register
 * @param[in] Variable to write the data to regitser
 * @return    None
 */

void
mcp2515_setRegisterS (
    const uint8_t address, const uint8_t values[], const uint8_t n)
{
    uint8_t i;
    mcp_select ();
    uint8_t set_registers[2] = { MCP_WRITE, address };
    spi_send_recv (SPI_MASTER_0, &set_registers, 2, &dummy_receive, 2);
  //  SEGGER_RTT_printf (
   //     0, "Address inside set register function : %x\r\n", address);

    for (i = 0; i < n; i++)
        {
            spi_send_recv (SPI_MASTER_0, &values[i], 1, &dummy_receive, 1);
        }
    mcp_unselect ();
}

/*!
 * @brief     To modify/re-write the register value by sending bit modify
 * instruction in first place
 *
 * @param[in] Address of register to write to
 * @param[in] MODE MASK , AND with result gives us the address we passed
 * @param[in] Data to write to the register
 * @return    None
 */

void
mcp2515_modifyRegister (
    const uint8_t address, const uint8_t mask, const uint8_t data)
{
    mcp_select ();

    uint8_t modify_reg[4] = { MCP_BITMOD, address, mask, data };

    spi_send_recv (SPI_MASTER_0, &modify_reg, 4, &dummy_receive, 4);

    mcp_unselect ();
}

/*!
 * @brief To read the status of different rx and tx bits. Places returned data
 * in array
 *
 * @param[in] None
 * @return Data returned on MISO Line
 */

uint8_t
mcp2515_readStatus (void)
{
    uint8_t i;
    mcp_select ();
    uint8_t read_status[2] = { MCP_READ_STATUS, 0x00 };
    uint8_t rx_status[2];
    spi_send_recv (SPI_MASTER_0, &read_status, 2, &rx_status, 2);

    mcp_unselect ();
    i = rx_status[1];

    return i;
}

/*!
 * @brief     To Set the mode
 *
 * @param[in] Mode Value in HEX
 * @return    0 : OK! ,1: FAIL
 */

uint8_t
mcp2515_setCANCTRL_Mode (const uint8_t newmode)
{
    uint8_t i;

    mcp2515_modifyRegister (MCP_CANCTRL, MODE_MASK, newmode);

    i = mcp2515_readRegister (MCP_CANCTRL);

    i &= MODE_MASK;

    if (i == newmode)
        {
            return MCP2515_OK;
        }

    return MCP2515_FAIL;
}

/*!
 * @brief     To Set the Baud Rate
 *
 * @param[in] Required Baud Rate Value
 *
 * @return    0 :OK , 1 : FAILURE
 */

uint8_t
mcp2515_configRate (const uint8_t canSpeed)
{
    uint8_t set, cfg1, cfg2, cfg3;
    set = 1;
    switch (canSpeed)
        {
        case (CAN_5KBPS):
            cfg1 = MCP_16MHz_5kBPS_CFG1;
            cfg2 = MCP_16MHz_5kBPS_CFG2;
            cfg3 = MCP_16MHz_5kBPS_CFG3;
            break;

        case (CAN_10KBPS):
            cfg1 = MCP_16MHz_10kBPS_CFG1;
            cfg2 = MCP_16MHz_10kBPS_CFG2;
            cfg3 = MCP_16MHz_10kBPS_CFG3;
            break;

        case (CAN_20KBPS):
            cfg1 = MCP_16MHz_20kBPS_CFG1;
            cfg2 = MCP_16MHz_20kBPS_CFG2;
            cfg3 = MCP_16MHz_20kBPS_CFG3;
            break;

        case (CAN_31K25BPS):
            cfg1 = MCP_16MHz_31k25BPS_CFG1;
            cfg2 = MCP_16MHz_31k25BPS_CFG2;
            cfg3 = MCP_16MHz_31k25BPS_CFG3;
            break;

        case (CAN_33KBPS):
            cfg1 = MCP_16MHz_33kBPS_CFG1;
            cfg2 = MCP_16MHz_33kBPS_CFG2;
            cfg3 = MCP_16MHz_33kBPS_CFG3;
            break;

        case (CAN_40KBPS):
            cfg1 = MCP_16MHz_40kBPS_CFG1;
            cfg2 = MCP_16MHz_40kBPS_CFG2;
            cfg3 = MCP_16MHz_40kBPS_CFG3;
            break;

        case (CAN_50KBPS):
            cfg1 = MCP_16MHz_50kBPS_CFG1;
            cfg2 = MCP_16MHz_50kBPS_CFG2;
            cfg3 = MCP_16MHz_50kBPS_CFG3;
            break;

        case (CAN_80KBPS):
            cfg1 = MCP_16MHz_80kBPS_CFG1;
            cfg2 = MCP_16MHz_80kBPS_CFG2;
            cfg3 = MCP_16MHz_80kBPS_CFG3;
            break;

        case (CAN_83K3BPS):
            cfg1 = MCP_16MHz_83k3BPS_CFG1;
            cfg2 = MCP_16MHz_83k3BPS_CFG2;
            cfg3 = MCP_16MHz_83k3BPS_CFG3;
            break;

        case (CAN_95KBPS):
            cfg1 = MCP_16MHz_95kBPS_CFG1;
            cfg2 = MCP_16MHz_95kBPS_CFG2;
            cfg3 = MCP_16MHz_95kBPS_CFG3;
            break;

        case (CAN_100KBPS): /* 100KBPS                  */
            cfg1 = MCP_16MHz_100kBPS_CFG1;
            cfg2 = MCP_16MHz_100kBPS_CFG2;
            cfg3 = MCP_16MHz_100kBPS_CFG3;
            break;

        case (CAN_125KBPS):
            cfg1 = MCP_16MHz_125kBPS_CFG1;
            cfg2 = MCP_16MHz_125kBPS_CFG2;
            cfg3 = MCP_16MHz_125kBPS_CFG3;
            break;

        case (CAN_200KBPS):
            cfg1 = MCP_16MHz_200kBPS_CFG1;
            cfg2 = MCP_16MHz_200kBPS_CFG2;
            cfg3 = MCP_16MHz_200kBPS_CFG3;
            break;

        case (CAN_250KBPS):
            cfg1 = MCP_16MHz_250kBPS_CFG1;
            cfg2 = MCP_16MHz_250kBPS_CFG2;
            cfg3 = MCP_16MHz_250kBPS_CFG3;
            break;

        case (CAN_500KBPS):
            cfg1 = MCP_16MHz_500kBPS_CFG1;
            cfg2 = MCP_16MHz_500kBPS_CFG2;
            cfg3 = MCP_16MHz_500kBPS_CFG3;
            break;

        case (CAN_1000KBPS):
            cfg1 = MCP_16MHz_1000kBPS_CFG1;
            cfg2 = MCP_16MHz_1000kBPS_CFG2;
            cfg3 = MCP_16MHz_1000kBPS_CFG3;
            break;

        default:
            set = 0;
            break;
        }

    if (set)
        {
            mcp2515_setRegister (MCP_CNF1, cfg1);
            mcp2515_setRegister (MCP_CNF2, cfg2);
            mcp2515_setRegister (MCP_CNF3, cfg3);
            return MCP2515_OK;
        }
    else
        {
            return MCP2515_FAIL;
        }
}

/*!
 * @brief     To Set the CAN Buffer Setting(Filters and Masks)
 *
 * @param[in] None
 *
 * @return None
 */

void
mcp2515_initCANBuffers (void)
{
    uint8_t i, a1, a2, a3;

    a1 = MCP_TXB0CTRL;
    a2 = MCP_TXB1CTRL;
    a3 = MCP_TXB2CTRL;
    for (i = 0; i < 14; i++)
        {
            mcp2515_setRegister (a1, 0);
            mcp2515_setRegister (a2, 0);
            mcp2515_setRegister (a3, 0);
            a1++;
            a2++;
            a3++;
        }
    mcp2515_setRegister (MCP_RXB0CTRL, 0);
    mcp2515_setRegister (MCP_RXB1CTRL, 0);
}

/*!
 * @brief     To initalize the CAN Module
 *
 * @param[in] Required Baud Rate of CAN.
 *
 * @return    0 : SUCESS 1: FAIL
 */

uint8_t
mcp2515_init (const uint8_t canSpeed)
{

    uint8_t res;

    mcp_can_reset ();

    res = mcp2515_setCANCTRL_Mode (MODE_CONFIG);

    if (res > 0)
        {
            SEGGER_RTT_printf (0, "Enter setting mode fail\r\n");

            nrf_delay_ms (10);

            return res;
        }

    nrf_delay_ms (10);

    SEGGER_RTT_printf (0, "Enter setting mode success \r\n");

    if (mcp2515_configRate (canSpeed))
        {

            SEGGER_RTT_printf (0, "set rate fail!!\r\n");

            nrf_delay_ms (10);

            return res;
        }

    SEGGER_RTT_printf (0, "set rate Success!!\r\n");

    nrf_delay_ms (10);

    if (res == MCP2515_OK)
        {

            mcp2515_initCANBuffers ();

            mcp2515_setRegister (MCP_CANINTE, MCP_RX0IF | MCP_RX1IF);

#if (DEBUG_RXANY == 1)
            /* enable both receive-buffers  */
            /* to receive any message       */
            /* and enable rollover          */
            mcp2515_modifyRegister (MCP_RXB0CTRL,
                MCP_RXB_RX_MASK | MCP_RXB_BUKT_MASK,
                MCP_RXB_RX_ANY | MCP_RXB_BUKT_MASK);
            mcp2515_modifyRegister (
                MCP_RXB1CTRL, MCP_RXB_RX_MASK, MCP_RXB_RX_ANY);
#else

            mcp2515_modifyRegister (MCP_RXB0CTRL,
                MCP_RXB_RX_MASK | MCP_RXB_BUKT_MASK,
                MCP_RXB_RX_STDEXT | MCP_RXB_BUKT_MASK);
            mcp2515_modifyRegister (
                MCP_RXB1CTRL, MCP_RXB_RX_MASK, MCP_RXB_RX_STDEXT);
#endif

            res = mcp2515_setCANCTRL_Mode (MODE_NORMAL);
            if (res)
                {
                    SEGGER_RTT_printf (0, "Enter Normal Mode Fail!!\r\n");
#if DEBUG_MODE
                    printf ("Enter Normal Mode Fall!!\r\n");
#else
                    nrf_delay_ms (10);
#endif
                    return res;
                }

            SEGGER_RTT_printf (0, "Enter Normal Mode Success!!\r\n");
#if DEBUG_MODE
            printf ("Enter Normal Mode Success!!\r\n");
#else
            nrf_delay_ms (10);
#endif
        }
    return res;
}

/*!
 * @brief     Write the CAN Standard or extended Identifier
 *
 * @param[in] Address of Register
 * @parma[in] Flag for Extended identifier
 * @param[in] Identifer to set
 *
 * @return    None
 */

void
mcp2515_write_id (const uint8_t mcp_addr, const uint8_t ext, const uint32_t id)
{
    uint16_t canid;
    uint8_t tbufdata[8];

    canid = (uint16_t) (id & 0x0FFFF);

    if (ext == 1)
        {
            tbufdata[MCP_EID0] = (uint8_t) (canid & 0xFF);
            tbufdata[MCP_EID8] = (uint8_t) (canid >> 8);
            canid = (uint16_t) (id >> 16);
            tbufdata[MCP_SIDL] = (uint8_t) (canid & 0x03);
            tbufdata[MCP_SIDL] += (uint8_t) ((canid & 0x1C) << 3);
            tbufdata[MCP_SIDL] |= MCP_TXB_EXIDE_M;
            tbufdata[MCP_SIDH] = (uint8_t) (canid >> 5);
        }
    else
        {

            tbufdata[MCP_SIDH] = (uint8_t) (canid >> 3);
            tbufdata[MCP_SIDL] = (uint8_t) ((canid & 0x07) << 5);
            tbufdata[MCP_EID0] = 0;
            tbufdata[MCP_EID8] = 0;
        }
    mcp2515_setRegisterS (mcp_addr, tbufdata, 4);
}

/*!
 * @brief     To read the ID of the incoming CAN Message
 *
 * @param[in] Address of Register
 * @parma[in] Flag for Extended identifier
 * @param[in] Identifer to Read
 *
 * @return    None
 */

void
mcp2515_read_id (const uint8_t mcp_addr, uint8_t *ext, uint32_t *id)
{
    uint8_t tbufdata[4];

    *ext = 0;
    *id = 0;

    mcp2515_readRegisterS (mcp_addr, tbufdata, 4);

    *id = (tbufdata[MCP_SIDH] << 3) + (tbufdata[MCP_SIDL] >> 5);

    if ((tbufdata[MCP_SIDL] & MCP_TXB_EXIDE_M) == MCP_TXB_EXIDE_M)
        {

            *id = (*id << 2) + (tbufdata[MCP_SIDL] & 0x03);
            *id = (*id << 8) + tbufdata[MCP_EID8];
            *id = (*id << 8) + tbufdata[MCP_EID0];
            *ext = 1;
        }
}

/*!
 * @brief     To Setup the CAN Messgae by setting Different Areas of CAN
 * Message
 *
 * @param[in] Address of Register
 *
 * @return    None
 */

void
mcp2515_write_canMsg (const uint8_t buffer_sidh_addr)
{

    uint8_t mcp_addr;
    mcp_addr = buffer_sidh_addr;
    // write data bytes
    mcp2515_setRegisterS (mcp_addr + 5, m_mcp_can.m_data, m_mcp_can.m_len);
    // write the RTR and DLC
    mcp2515_setRegister ((mcp_addr + 4), m_mcp_can.m_len);
    // write CAN id
    mcp2515_write_id (mcp_addr, m_mcp_can.m_ext_flag, m_mcp_can.m_id);
}

/*!
 * @brief     To Read the CAN Message
 *
 * @param[in] Address of Register
 *
 * @return    None
 */

void
mcp2515_read_canMsg (const uint8_t buffer_sidh_addr)
{
    uint8_t mcp_addr, ctrl;

    mcp_addr = buffer_sidh_addr;

    mcp2515_read_id (mcp_addr, &m_mcp_can.m_ext_flag, &m_mcp_can.m_id);

    ctrl = mcp2515_readRegister (mcp_addr - 1);
    m_mcp_can.m_len = mcp2515_readRegister (mcp_addr + 4);

    m_mcp_can.m_len &= MCP_DLC_MASK;
    mcp2515_readRegisterS (
        mcp_addr + 5, &(m_mcp_can.m_data[0]), m_mcp_can.m_len);
}

/*!
 * @brief     To start the transmission of message via CAN
 *
 * @param[in] Address of Transmit Register
 *
 * @return    None
 */

void
mcp2515_start_transmit (const uint8_t mcp_addr)
{

    mcp2515_modifyRegister (mcp_addr - 1, MCP_TXB_TXREQ_M, MCP_TXB_TXREQ_M);
}

/*!
 * @brief     To Get the next free Tx Buffer ,if previous one is filled
 *
 * @param[in] Address of Transmit Buffer Register
 *
 * @return    0 : OK , 2 : All Buffer Full
 */

uint8_t
mcp2515_getNextFreeTXBuf (uint8_t *txbuf_n)
{

    uint8_t res, i, ctrlval;
    uint8_t ctrlregs[MCP_N_TXBUFFERS] = { MCP_TXB0CTRL, MCP_TXB1CTRL,
        MCP_TXB2CTRL };

    res = MCP_ALLTXBUSY;
    *txbuf_n = 0x00;

    // check all 3 TX-Buffers
    for (i = 0; i < MCP_N_TXBUFFERS; i++)
        {
            ctrlval = mcp2515_readRegister (ctrlregs[i]);
            if ((ctrlval & MCP_TXB_TXREQ_M) == 0)
                {
                    *txbuf_n = ctrlregs[i] + 1;

                    res = MCP2515_OK;
                    return res;
                }
        }
    return res;
}

/*!
 * @brief     To Load the message into Global Structure Variables
 *
 * @param[in] Identifier to send the message with
 * @param[in] Flag for Extended Identifier
 * @param[in] Length of Data to be sent
 * @param[in] Address of the pointer data to be sent
 *
 * @return    0 : OK
 */

uint8_t
setMsg (uint32_t id, uint8_t ext, uint8_t len, uint8_t *pData)
{
    int i = 0;
    m_mcp_can.m_ext_flag = 0; // ext;
    m_mcp_can.m_id = id;
    m_mcp_can.m_len = len;
    for (i = 0; i < MAX_CHAR_IN_MESSAGE; i++)
        {
            m_mcp_can.m_data[i] = *(pData + i);
        }
    return MCP2515_OK;
}

/*!
 * @brief     To Clear the message parameters
 *
 * @param[in] None
 *
 * @return    0 : OK
 */

uint8_t
clearMsg ()
{
    m_mcp_can.m_id = 0;
    m_mcp_can.m_len = 0;
    m_mcp_can.m_ext_flag = 0;
    for (int i = 0; i < m_mcp_can.m_len; i++)
        m_mcp_can.m_data[i] = 0x00;

    return MCP2515_OK;
}

/*!
 * @brief     To Send the message via CAN Bus
 *
 * @param[in] None
 *
 * @return    0 : OK , 7 : Messge Sent Timeout , 6 : Buffer Full Timoeut
 */

uint8_t
sendMsg ()
{
    uint8_t res, res1, txbuf_n;
    uint16_t uiTimeOut = 0;

    do
        {
            res = mcp2515_getNextFreeTXBuf (&txbuf_n);

            uiTimeOut++;
        }
    while (res == MCP_ALLTXBUSY && (uiTimeOut < TIMEOUTVALUE));

    if (uiTimeOut == TIMEOUTVALUE)
        {
            spi_master_uninit ();
            return CAN_GETTXBFTIMEOUT;

        }
    uiTimeOut = 0;
   // SEGGER_RTT_printf (0, "TXBUFFER :%x\r\n", txbuf_n);
    mcp2515_write_canMsg (txbuf_n);
    mcp2515_start_transmit (txbuf_n);
    do
        {
            uiTimeOut++;
            res1 = mcp2515_readRegister (txbuf_n - 1);

            res1 = res1 & 0x08;
        }
    while (res1 && (uiTimeOut < TIMEOUTVALUE));
    if (uiTimeOut == TIMEOUTVALUE)
        {
            spi_master_uninit ();
            return CAN_SENDMSGTIMEOUT;
        }
    spi_master_uninit ();

    return CAN_OK;
}

/*!
 * @brief     To Read the incoming message
 *
 * @param[in] None
 *
 * @return    0 : OK , 4 : No message was Received
 */

uint8_t
readMsg ()
{
    uint8_t stat, res;

    stat = mcp2515_readStatus ();

    if (stat & MCP_STAT_RX0IF)
        {
            mcp2515_read_canMsg (MCP_RXBUF_0);
            mcp2515_modifyRegister (MCP_CANINTF, MCP_RX0IF, 0);
            res = CAN_OK;
        }
    else if (stat & MCP_STAT_RX1IF)
        {
            mcp2515_read_canMsg (MCP_RXBUF_1);
            mcp2515_modifyRegister (MCP_CANINTF, MCP_RX1IF, 0);
            res = CAN_OK;
        }
    else
        {
            res = CAN_NOMSG;
        }
    return res;
}

// NOTE : THIS FUNCTION IS NOT CALLED ANYWHERE , JUST TO BE SAFE I AM NOT
// DELETING IT :p

void
mcp_can_setcs (uint8_t cs)
{
    m_mcp_can.m_cs = cs;
    nrf_gpio_cfg_output (m_mcp_can.m_cs);
    mcp_unselect ();
}

/*!
 * @brief     To Initialize the CAN With Required Baud Rate
 *
 * @param[in] Baud Rate Required
 *
 * @return    0 : OK , 1 : Failed Initializing
 */

uint8_t
mcp_can_begin (uint8_t speedset)
{
    uint8_t res;

    spi_master_init (SPI_MASTER_0, spi_master_0_event_handler);

    res = mcp2515_init (speedset);
    
    spi_master_uninit ();
    if (res == MCP2515_OK)
        return CAN_OK;
    else
        return CAN_FAILINIT;
}

/*!
 * @brief     To send the message by first creating the format
 *
 * @param[in] Identifier with which message will be sent
 * @param[in] Flag for extended identifier
 * @param[in] Length of data to be Sent
 * @param[in] Address of Pointer to data which is needed to be sent
 *
 * @return    Value Retuned by sendMsg() Function
 */

uint8_t
mcp_can_send_msg (uint32_t id, uint8_t ext, uint8_t len, uint8_t *buf)
{   
    spi_master_init (SPI_MASTER_0,spi_master_0_event_handler);
    setMsg (id, ext, len, buf);
    return sendMsg ();
}

/*!
 * @brief     To Read the CAN Message
 *
 * @param[in] Identifier To store the id of message
 * @param[in] Length to be received
 * @param[in] Buffer to store the received Data
 *
 * @return    Value Retuned by readMsg() Function
 */

uint8_t
mcp_can_read_msg (uint32_t *ID, uint8_t *len, uint8_t buf[])
{
    uint8_t rc;
    spi_master_init (SPI_MASTER_0,spi_master_0_event_handler);
    rc = readMsg ();

    if (rc == CAN_OK)
        {
            *len = m_mcp_can.m_len;
            *ID = m_mcp_can.m_id;
            for (int i = 0; i < m_mcp_can.m_len && i < MAX_CHAR_IN_MESSAGE;
                 i++)
                {
                    buf[i] = m_mcp_can.m_data[i];
                }
        }
    else
        {
            *len = 0;
        }
    spi_master_uninit ();
    return rc;
}

/*!
 * @brief     To Check the Receive Message Register
 *
 * @param[in] None
 *
 * @return    3 : Message AVailable , 4 : No Message Available
 */

uint8_t
mcp_can_check_receive (void)
{
    uint8_t res;
    spi_master_init (SPI_MASTER_0,spi_master_0_event_handler);
    res = mcp2515_readStatus ();
    spi_master_uninit ();
    if (res & MCP_STAT_RXIF_MASK)
        {
            return CAN_MSGAVAIL;
        }
    else
        {
            return CAN_NOMSG;
        }
}

/*!
 * @brief     To Check if any Error Occured on Bus
 *
 * @param[in] None
 *
 * @return    5 : CAN CONTROL REGISTER ERROR , 0 : OK
 */

uint8_t
mcp_can_check_error (void)
{
    uint8_t eflg = mcp2515_readRegister (MCP_EFLG);

    if (eflg & MCP_EFLG_ERRORMASK)
        {
            return CAN_CTRLERROR;
        }
    else
        {
            return CAN_OK;
        }
}