#pragma once

#include <stdint.h>
#include "F28335/DSP28x_Project.h"
#include "F28335/DSP2833x_Device.h"

#include "CAN_data.h"

namespace can_space {

class CAN{
public:
    CAN(CAN_VARIANT canVariant);

    void initGpio();
    void config(uint16_t baudrate = 1000, uint16_t flags = 0);
    void configTxMBox(uint16_t boxNumber, const MsgID& configID, const MsgCtrlReg& configCtrlReg);
    void configRxMBox(uint16_t boxNumber, const MsgID& configID, const MsgCtrlReg& configCtrlReg);
    void configSystemIsr(uint32_t flags);
    void configMBoxIsr(uint16_t boxNumber);

    bool isNewMessage();
    bool isNewMessage(uint16_t boxNumber);

    void transmitMsg(uint16_t boxNumber, const CANMessage& message, bool writeDataLength = false);
    void transmitMsg(uint16_t boxNumber, const uint64_t& message, const uint16_t dlc);
    void transmitMsg(uint16_t boxNumber, const uint64_t& message);
    void updateTXMessage(uint16_t boxNumber, const CANMessage& message);
    void sendRemoteRequest(uint16_t boxNumber);
    int16_t receiveMsg(uint16_t boxNumber, CANMessage& rxMessage);

    void enableTimeOutControl(uint16_t boxNumber);
    void disableTimeOutControl(uint16_t boxNumber);
    void resetTimeStampCounter();
    void setTimeOutValue(uint16_t boxNumber, uint32_t canBitsNumber);
    bool isTimeOut(uint16_t boxNumber);
    void clearTimeOutFlag(uint16_t boxNumber);

    void busErrorInterruptFlagsReset();

private:
    CAN_VARIANT _canPort;
    volatile ECAN_REGS* _p_CanRegs;
    ECAN_REGS _CanShadow;
    volatile ECAN_MBOXES* _p_CanMBoxes;
    volatile MOTO_REGS* _p_CanMotoRegs;
    volatile MOTS_REGS* _p_CanMotsRegs;
};


}   // can_space