Skip to content

Commit 032a0fc

Browse files
committed
Add HardwareCAN - a abstract base class for implementing CAN interfaces across Arduino cores.
1 parent 844e4bf commit 032a0fc

File tree

4 files changed

+281
-0
lines changed

4 files changed

+281
-0
lines changed

api/CanMsg.h

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* This file is free software; you can redistribute it and/or modify
3+
* it under the terms of either the GNU General Public License version 2
4+
* or the GNU Lesser General Public License version 2.1, both as
5+
* published by the Free Software Foundation.
6+
*/
7+
8+
#ifndef ARDUINOCORE_API_CAN_MSG_H_
9+
#define ARDUINOCORE_API_CAN_MSG_H_
10+
11+
/**************************************************************************************
12+
* INCLUDE
13+
**************************************************************************************/
14+
15+
#include <cstdlib>
16+
#include <cstdint>
17+
#include <cstring>
18+
19+
#include <Arduino.h>
20+
21+
/**************************************************************************************
22+
* NAMESPACE
23+
**************************************************************************************/
24+
25+
namespace arduino
26+
{
27+
28+
/**************************************************************************************
29+
* CLASS DECLARATION
30+
**************************************************************************************/
31+
32+
class CanMsg : public Printable
33+
{
34+
public:
35+
static size_t constexpr MAX_DATA_LENGTH = 8;
36+
37+
CanMsg(uint32_t const can_id, uint8_t const can_data_len, uint8_t const * can_data_ptr)
38+
: id{can_id}
39+
, data_length{can_data_len}
40+
, data{0}
41+
{
42+
memcpy(data, can_data_ptr, min(can_data_len, MAX_DATA_LENGTH));
43+
}
44+
45+
CanMsg() : CanMsg(0, 0, nullptr) { }
46+
47+
CanMsg(CanMsg const & other)
48+
{
49+
this->id = other.id;
50+
this->data_length = other.data_length;
51+
memcpy(this->data, other.data, this->data_length);
52+
}
53+
54+
virtual ~CanMsg() { }
55+
56+
void operator = (CanMsg const & other)
57+
{
58+
if (this == &other)
59+
return;
60+
61+
this->id = other.id;
62+
this->data_length = other.data_length;
63+
memcpy(this->data, other.data, this->data_length);
64+
}
65+
66+
virtual size_t printTo(Print & p) const override
67+
{
68+
char buf[20] = {0};
69+
size_t len = 0;
70+
71+
/* Print the header. */
72+
len = snprintf(buf, sizeof(buf), "[%08X] (%d) : ", id, data_length);
73+
size_t n = p.write(buf, len);
74+
75+
/* Print the data. */
76+
for (size_t d = 0; d < data_length; d++)
77+
{
78+
len = snprintf(buf, sizeof(buf), "%02X", data[d]);
79+
n += p.write(buf, len);
80+
}
81+
82+
/* Wrap up. */
83+
return n;
84+
}
85+
86+
uint32_t id;
87+
uint8_t data_length;
88+
uint8_t data[MAX_DATA_LENGTH];
89+
};
90+
91+
/**************************************************************************************
92+
* NAMESPACE
93+
**************************************************************************************/
94+
95+
} /* arduino */
96+
97+
#endif /* ARDUINOCORE_API_CAN_MSG_H_ */

api/CanMsgRingbuffer.cpp

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* This file is free software; you can redistribute it and/or modify
3+
* it under the terms of either the GNU General Public License version 2
4+
* or the GNU Lesser General Public License version 2.1, both as
5+
* published by the Free Software Foundation.
6+
*/
7+
8+
/**************************************************************************************
9+
* INCLUDE
10+
**************************************************************************************/
11+
12+
#include "CanMsgRingbuffer.h"
13+
14+
/**************************************************************************************
15+
* NAMESPACE
16+
**************************************************************************************/
17+
18+
namespace arduino
19+
{
20+
21+
/**************************************************************************************
22+
* CTOR/DTOR
23+
**************************************************************************************/
24+
25+
CanMsgRingbuffer::CanMsgRingbuffer()
26+
: _head{0}
27+
, _tail{0}
28+
, _num_elems{0}
29+
{
30+
}
31+
32+
/**************************************************************************************
33+
* PUBLIC MEMBER FUNCTIONS
34+
**************************************************************************************/
35+
36+
void CanMsgRingbuffer::enqueue(CanMsg const & msg)
37+
{
38+
if (isFull())
39+
return;
40+
41+
_buf[_head] = msg;
42+
_head = next(_head);
43+
_num_elems++;
44+
}
45+
46+
CanMsg CanMsgRingbuffer::dequeue()
47+
{
48+
if (isEmpty())
49+
return CanMsg();
50+
51+
CanMsg const msg = _buf[_tail];
52+
_tail = next(_tail);
53+
_num_elems--;
54+
55+
return msg;
56+
}
57+
58+
/**************************************************************************************
59+
* NAMESPACE
60+
**************************************************************************************/
61+
62+
} /* arduino */

api/CanMsgRingbuffer.h

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* This file is free software; you can redistribute it and/or modify
3+
* it under the terms of either the GNU General Public License version 2
4+
* or the GNU Lesser General Public License version 2.1, both as
5+
* published by the Free Software Foundation.
6+
*/
7+
8+
#ifndef ARDUINOCORE_API_CAN_MSG_RING_BUFFER_H_
9+
#define ARDUINOCORE_API_CAN_MSG_RING_BUFFER_H_
10+
11+
/**************************************************************************************
12+
* INCLUDE
13+
**************************************************************************************/
14+
15+
#include <cstdint>
16+
17+
#include "CanMsg.h"
18+
19+
/**************************************************************************************
20+
* NAMESPACE
21+
**************************************************************************************/
22+
23+
namespace arduino
24+
{
25+
26+
/**************************************************************************************
27+
* CLASS DECLARATION
28+
**************************************************************************************/
29+
30+
class CanMsgRingbuffer
31+
{
32+
public:
33+
static size_t constexpr RING_BUFFER_SIZE = 32U;
34+
35+
CanMsgRingbuffer();
36+
37+
inline bool isFull() const { return (_num_elems == RING_BUFFER_SIZE); }
38+
void enqueue(CanMsg const & msg);
39+
40+
inline bool isEmpty() const { return (_num_elems == 0); }
41+
CanMsg dequeue();
42+
43+
inline size_t available() const { return _num_elems; }
44+
45+
private:
46+
CanMsg _buf[RING_BUFFER_SIZE];
47+
volatile size_t _head;
48+
volatile size_t _tail;
49+
volatile size_t _num_elems;
50+
51+
inline size_t next(size_t const idx) const { return ((idx + 1) % RING_BUFFER_SIZE); }
52+
};
53+
54+
/**************************************************************************************
55+
* NAMESPACE
56+
**************************************************************************************/
57+
58+
} /* arduino */
59+
60+
#endif /* ARDUINOCORE_API_CAN_MSG_RING_BUFFER_H_ */

api/HardwareCAN.h

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* This file is free software; you can redistribute it and/or modify
3+
* it under the terms of either the GNU General Public License version 2
4+
* or the GNU Lesser General Public License version 2.1, both as
5+
* published by the Free Software Foundation.
6+
*/
7+
8+
#ifndef ARDUINOCORE_API_HARDWARECAN_H
9+
#define ARDUINOCORE_API_HARDWARECAN_H
10+
11+
/**************************************************************************************
12+
* INCLUDE
13+
**************************************************************************************/
14+
15+
#include "CanMsg.h"
16+
#include "CanMsgRingbuffer.h"
17+
18+
/**************************************************************************************
19+
* TYPEDEF
20+
**************************************************************************************/
21+
22+
enum class CanBitRate : int
23+
{
24+
BR_125k = 125000,
25+
BR_250k = 250000,
26+
BR_500k = 500000,
27+
BR_1000k = 1000000,
28+
};
29+
30+
/**************************************************************************************
31+
* NAMESPACE
32+
**************************************************************************************/
33+
34+
namespace arduino
35+
{
36+
37+
/**************************************************************************************
38+
* CLASS DECLARATION
39+
**************************************************************************************/
40+
41+
class HardwareCAN
42+
{
43+
public:
44+
virtual ~HardwareCAN() {}
45+
46+
47+
virtual bool begin(CanBitRate const can_bitrate) = 0;
48+
virtual void end() = 0;
49+
50+
51+
virtual int write(CanMsg const &msg) = 0;
52+
virtual size_t available() = 0;
53+
virtual CanMsg read() = 0;
54+
};
55+
56+
/**************************************************************************************
57+
* NAMESPACE
58+
**************************************************************************************/
59+
60+
} /* arduino */
61+
62+
#endif /* ARDUINOCORE_API_HARDWARECAN_H */

0 commit comments

Comments
 (0)