diff --git a/api/CanMsg.h b/api/CanMsg.h new file mode 100644 index 00000000..6021564a --- /dev/null +++ b/api/CanMsg.h @@ -0,0 +1,97 @@ +/* + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#ifndef ARDUINOCORE_API_CAN_MSG_H_ +#define ARDUINOCORE_API_CAN_MSG_H_ + +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + +#include +#include +#include + +#include + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +namespace arduino +{ + +/************************************************************************************** + * CLASS DECLARATION + **************************************************************************************/ + +class CanMsg : public Printable +{ +public: + static size_t constexpr MAX_DATA_LENGTH = 8; + + CanMsg(uint32_t const can_id, uint8_t const can_data_len, uint8_t const * can_data_ptr) + : id{can_id} + , data_length{can_data_len} + , data{0} + { + memcpy(data, can_data_ptr, min(can_data_len, MAX_DATA_LENGTH)); + } + + CanMsg() : CanMsg(0, 0, nullptr) { } + + CanMsg(CanMsg const & other) + { + this->id = other.id; + this->data_length = other.data_length; + memcpy(this->data, other.data, this->data_length); + } + + virtual ~CanMsg() { } + + void operator = (CanMsg const & other) + { + if (this == &other) + return; + + this->id = other.id; + this->data_length = other.data_length; + memcpy(this->data, other.data, this->data_length); + } + + virtual size_t printTo(Print & p) const override + { + char buf[20] = {0}; + size_t len = 0; + + /* Print the header. */ + len = snprintf(buf, sizeof(buf), "[%08X] (%d) : ", id, data_length); + size_t n = p.write(buf, len); + + /* Print the data. */ + for (size_t d = 0; d < data_length; d++) + { + len = snprintf(buf, sizeof(buf), "%02X", data[d]); + n += p.write(buf, len); + } + + /* Wrap up. */ + return n; + } + + uint32_t id; + uint8_t data_length; + uint8_t data[MAX_DATA_LENGTH]; +}; + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +} /* arduino */ + +#endif /* ARDUINOCORE_API_CAN_MSG_H_ */ diff --git a/api/CanMsgRingbuffer.cpp b/api/CanMsgRingbuffer.cpp new file mode 100644 index 00000000..c358a10a --- /dev/null +++ b/api/CanMsgRingbuffer.cpp @@ -0,0 +1,62 @@ +/* + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + +#include "CanMsgRingbuffer.h" + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +namespace arduino +{ + +/************************************************************************************** + * CTOR/DTOR + **************************************************************************************/ + +CanMsgRingbuffer::CanMsgRingbuffer() +: _head{0} +, _tail{0} +, _num_elems{0} +{ +} + +/************************************************************************************** + * PUBLIC MEMBER FUNCTIONS + **************************************************************************************/ + +void CanMsgRingbuffer::enqueue(CanMsg const & msg) +{ + if (isFull()) + return; + + _buf[_head] = msg; + _head = next(_head); + _num_elems++; +} + +CanMsg CanMsgRingbuffer::dequeue() +{ + if (isEmpty()) + return CanMsg(); + + CanMsg const msg = _buf[_tail]; + _tail = next(_tail); + _num_elems--; + + return msg; +} + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +} /* arduino */ diff --git a/api/CanMsgRingbuffer.h b/api/CanMsgRingbuffer.h new file mode 100644 index 00000000..9218ef88 --- /dev/null +++ b/api/CanMsgRingbuffer.h @@ -0,0 +1,60 @@ +/* + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#ifndef ARDUINOCORE_API_CAN_MSG_RING_BUFFER_H_ +#define ARDUINOCORE_API_CAN_MSG_RING_BUFFER_H_ + +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + +#include + +#include "CanMsg.h" + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +namespace arduino +{ + +/************************************************************************************** + * CLASS DECLARATION + **************************************************************************************/ + +class CanMsgRingbuffer +{ +public: + static size_t constexpr RING_BUFFER_SIZE = 32U; + + CanMsgRingbuffer(); + + inline bool isFull() const { return (_num_elems == RING_BUFFER_SIZE); } + void enqueue(CanMsg const & msg); + + inline bool isEmpty() const { return (_num_elems == 0); } + CanMsg dequeue(); + + inline size_t available() const { return _num_elems; } + +private: + CanMsg _buf[RING_BUFFER_SIZE]; + volatile size_t _head; + volatile size_t _tail; + volatile size_t _num_elems; + + inline size_t next(size_t const idx) const { return ((idx + 1) % RING_BUFFER_SIZE); } +}; + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +} /* arduino */ + +#endif /* ARDUINOCORE_API_CAN_MSG_RING_BUFFER_H_ */ diff --git a/api/HardwareCAN.h b/api/HardwareCAN.h new file mode 100644 index 00000000..6dc87ebc --- /dev/null +++ b/api/HardwareCAN.h @@ -0,0 +1,62 @@ +/* + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#ifndef ARDUINOCORE_API_HARDWARECAN_H +#define ARDUINOCORE_API_HARDWARECAN_H + +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + +#include "CanMsg.h" +#include "CanMsgRingbuffer.h" + +/************************************************************************************** + * TYPEDEF + **************************************************************************************/ + +enum class CanBitRate : int +{ + BR_125k = 125000, + BR_250k = 250000, + BR_500k = 500000, + BR_1000k = 1000000, +}; + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +namespace arduino +{ + +/************************************************************************************** + * CLASS DECLARATION + **************************************************************************************/ + +class HardwareCAN +{ +public: + virtual ~HardwareCAN() {} + + + virtual bool begin(CanBitRate const can_bitrate) = 0; + virtual void end() = 0; + + + virtual int write(CanMsg const &msg) = 0; + virtual size_t available() = 0; + virtual CanMsg read() = 0; +}; + +/************************************************************************************** + * NAMESPACE + **************************************************************************************/ + +} /* arduino */ + +#endif /* ARDUINOCORE_API_HARDWARECAN_H */