src/ArduinoMCP2515.h
/**
 * This software is distributed under the terms of the MIT License.
 * Copyright (c) 2020 LXRobotics.
 * Author: Alexander Entinger <alexander.entinger@lxrobotics.com>
 * Contributors: https://github.com/107-systems/107-Arduino-MCP2515/graphs/contributors.
 */

#ifndef ARDUINO_MCP2515_H_
#define ARDUINO_MCP2515_H_

/**************************************************************************************
 * INCLUDE
 **************************************************************************************/

#include <stdint.h>
#include <stdbool.h>

#include "MCP2515/MCP2515_Io.h"
#include "MCP2515/MCP2515_Config.h"
#include "MCP2515/MCP2515_Control.h"
#include "MCP2515/MCP2515_Types.h"

#undef min
#undef max
#include <vector>
#include <string>
#include <functional>

#if defined __has_include
#  if __has_include (<libcanard/canard.h>)
#    include <libcanard/canard.h>
#    define LIBCANARD 1
#  elif __has_include (<canard.h>)
#    include <canard.h>
#    define LIBCANARD 1
#  endif
#else
#  define LIBCANARD 0
#endif

/**************************************************************************************
 * TYPEDEF
 **************************************************************************************/

#if LIBCANARD
typedef std::function<void(CanardFrame const & frame)> OnReceiveBufferFullFunc;
#else
typedef std::function<void(uint32_t const, uint32_t const, uint8_t const *, uint8_t const)> OnReceiveBufferFullFunc;
#endif

/**************************************************************************************
 * CLASS DECLARATION
 **************************************************************************************/

class ArduinoMCP2515
{

public:

  ArduinoMCP2515(MCP2515::SpiSelectFunc select,
                 MCP2515::SpiDeselectFunc deselect,
                 MCP2515::SpiTransferFunc transfer,
                 MicroSecondFunc micros,
                 MilliSecondFunc millis,
                 OnReceiveBufferFullFunc on_rx_buf_full,
                 OnTransmitBufferEmptyFunc on_tx_buf_empty,
                 OnCanErrorFunc on_error,
                 OnCanWarningFunc on_warning);

  ArduinoMCP2515(MCP2515::SpiSelectFunc select,
                 MCP2515::SpiDeselectFunc deselect,
                 MCP2515::SpiTransferFunc transfer,
                 MicroSecondFunc micros,
                 MilliSecondFunc millis,
                 OnReceiveBufferFullFunc on_rx_buf_full,
                 OnTransmitBufferEmptyFunc on_tx_buf_empty)
  : ArduinoMCP2515{select, deselect, transfer, micros, millis, on_rx_buf_full, on_tx_buf_empty, nullptr, nullptr}
  { }


  void begin();

  void setBitRate(CanBitRate const bit_rate);

  inline bool setNormalMode    () { return _cfg.setMode(MCP2515::Mode::Normal);     }
  inline bool setSleepMode     () { return _cfg.setMode(MCP2515::Mode::Sleep);      }
  inline bool setLoopbackMode  () { return _cfg.setMode(MCP2515::Mode::Loopback);   }
  inline bool setListenOnlyMode() { return _cfg.setMode(MCP2515::Mode::ListenOnly); }
  inline bool setConfigMode    () { return _cfg.setMode(MCP2515::Mode::Config);     }

  void enableFilter(MCP2515::RxB const rxb, uint32_t const mask, uint32_t const * filter, size_t const filter_size);

#if LIBCANARD
  bool transmit(CanardFrame const & frame);
#else
  bool transmit(uint32_t const id, uint8_t const * data, uint8_t const len);
#endif

  void onExternalEventHandler();


private:

  MCP2515::MCP2515_Io _io;
  MCP2515::MCP2515_Config _cfg;
  MCP2515::MCP2515_Control _ctrl;
  MicroSecondFunc _micros;
  OnReceiveBufferFullFunc _on_rx_buf_full;
  OnTransmitBufferEmptyFunc _on_tx_buf_empty;
  OnCanErrorFunc _on_error;
  OnCanWarningFunc _on_warning;

  bool transmitCANFrame        (uint32_t const id, uint8_t const * data, uint8_t const len);
  void onReceiveBuffer_0_Full  ();
  void onReceiveBuffer_1_Full  ();
  void onTransmitBuffer_0_Empty();
  void onTransmitBuffer_1_Empty();
  void onTransmitBuffer_2_Empty();
  void onReceiveBuffer_n_Full  (unsigned long const timestamp_us, uint32_t const id, uint8_t const * data, uint8_t const len) const;
};

#endif /* ARDUINO_MCP2515_H_ */
