-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCanNode.h
267 lines (244 loc) · 8.91 KB
/
CanNode.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
/**
* \file CanNode.h
* \brief Interface for using CanNode devices.
*
* CanNode.h provides high-level functions for protocol implementation.
* Driver level functions are in can.h. This compilation unit has a goal to be
* easily portable to a PC application.
*
* \author Samuel Ellicott
* \date 6-20-16
*/
#ifndef _CAN_NODE_H_
#define _CAN_NODE_H_
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <cstdbool>
#include "CanTypes.h"
#include "can_driver.h" // low level CAN driver
using std::int8_t;
using std::uint8_t;
using std::int16_t;
using std::uint16_t;
using std::int32_t;
using std::uint32_t;
/**
* \typedef filterHandler
* \brief Function pointer to a function that accepts a CanMessage pointer
*
* A function of this type should look like
*
* <code> void foo(CanMessage* msg) </code>
*
* Functions of this type can be used to handle filter matches. These functions
* are added set to handle filters with the CanNode_addFilter() function. They
* are
* called by the CanNode_checkForMessages() function
*
* \see CanNode::addFilter
* \see CanNode::checkForMessages
*/
typedef void (*filterHandler)(CanMessage *data);
/** \addtogroup CanNode_Module CanNode
* \brief Library to provide a higher level protocol for CAN communication.
* Specifically for stm32 microcontrollers
*
* A CanNode should be initilized with CanNode_init() this will return a pointer
*to
* an initilized node to be used with the other functions. Callbacks to occur on
* messages from a particular id can be added to a node with the
*CanNode_addFilter()
* function. To translate [CanMessages](\ref CanMessage) to useful data, use the
* getData functions. Data can be sent from a node with the sendData functions.
*
* ### Initilizing a node ###
*
* In order to send data and use filter callbacks you need to initilize a node.
* to do this call CanNode_init(), passing in a CanNodeType (acts like an id), a
* filterHandler for handling RTR (Retrun Transmission Request) callbacks for
* that node, this returns a CanNode pointer to
* a newly initilized CanNode struct. You can initilize up to \ref MAX_NODES
* nodes in this way.
*
* Example code
* ~~~~~~~~~~~~ {.c}
*
* //this allows you to access the node outside of the main function
* CanNode* newNodePtr;
* void pitotRTR(CanMessage* msg);
*
* void main(){
* CanNode newNode(PITOT, pitotRTR);
* newNodePtr = &newNode;
* //other stuff here
* //...
* }
*
* void pitotRTR(CanMessage* msg){
* //continue to do what needs to be done.
* uint16_t data = getSensorData();
* //call one of the \ref sendData functions to return the data
* newNodePtr->sendData_uint16_t(data);
* }
* ~~~~~~~~~~~~
*
* Another often useful thing to do is add filters
*
* ### Adding filters ###
*
* This is how to add a filter for a single id
*
* Example code
*
* ~~~~~~~~~~~~ {.c}
* CanNode* nodePtr;
* const uint16_t filterId = 1200;
* //initilize node
* //...
* nodePtr->addFilter(filterId, handler);
* ~~~~~~~~~~~~
*
* This is how a filter mask is added (data from multiple ids).
*
* Example code
*
* ~~~~~~~~~~~~ {.c}
* CanNode* nodePtr;
* //initilize node
* //...
* uint16_t id = can_add_filter_mask(id_to_filter, id_mask);
* nodePtr->addFilter(id, handler);
* ~~~~~~~~~~~~
*@{
*/
/**
* \defgroup CanNode_Functions CanNode Public Functions
*
* \brief Functions for interfacing with the CanNode struct, reciving and sending
* CAN messages.
*
*@{
*/
class CanNode {
private:
static bool newMessage;
static CanMessage tmpMsg;
static CanNode *nodes[MAX_NODES];
uint16_t id; ///< id of the node
uint8_t status; ///< status of the node (not currently used)
uint16_t filters[NUM_FILTERS]; ///< array of id's to handle
filterHandler rtrHandle; ///< function to handle rtr requests for
/// the node
filterHandler handle[NUM_FILTERS]; ///< array of function pointers to call
///< when a id in filters is found
CanNodeType sensorType; ///< Type of sensor
const char *nameStr; ///< points to the name of the node
const char *infoStr; ///< points to the info string for the node
public:
/// \brief Initilize a CanNode from given parameters.
CanNode(CanNodeType id, filterHandler rtrHandle);
/// \brief Add a filter and handler to a given CanNode.
bool addFilter(uint16_t filter, filterHandler handle);
/// \brief Check all initilized CanNodes for messages and call callbacks.
static void checkForMessages();
/**
* \anchor sendData
* \name sendData Functions
* These functions that send data over the CANBus and support various integer
* types of data. They are non-blocking.
* @{
*/
/// \brief Send a signed 8-bit integer.
void sendData_int8(int8_t data) const;
/// \brief Send an unsigned 8-bit integer.
void sendData_uint8(uint8_t data) const;
/// \brief Send a signed 16-bit integer.
void sendData_int16(int16_t data) const;
/// \brief Send an unsigned 16-bit integer.
void sendData_uint16(uint16_t data) const;
/// \brief Send a signed 32-bit integer.
void sendData_int32(int32_t data) const;
/// \brief Send an unsigned 32-bit integer.
void sendData_uint32(uint32_t data) const;
/// \brief Send a custom CanMessage.
void sendData_custom(CanMessage* data) const;
/// \brief Send an array of uinsigned 8-bit integers.
CanState sendDataArr_int8(int8_t *data, uint8_t len) const;
/// \brief Send an array of signed 8-bit integers.
CanState sendDataArr_uint8(uint8_t *data, uint8_t len) const;
/// \brief Send an array of uinsigned 16-bit integers.
CanState sendDataArr_int16(int16_t *data, uint8_t len) const;
/// \brief Send an array of signed 16-bit integers.
CanState sendDataArr_uint16(uint16_t *data, uint8_t len) const;
//@}
/**
* \anchor getData
* \name getData Functions
* These functions get data of various integer types from a CanMessage. They
* are
* non-blocking. If the data is not of the same type as the called function
* \ref INVALID_TYPE is returned.
*
* These functions are useful for data parsing in a handler function, since a
* CanMessage is passed as an argument to the function.
* @{
*/
/// \brief Get a signed 8-bit integer from a CanMessage.
static CanState getData_int8(const CanMessage *msg, int8_t *data);
/// \brief Get an unsigned 8-bit integer from a CanMessage.
static CanState getData_uint8(const CanMessage *msg, uint8_t *data);
/// \brief Get a signed 16-bit integer from a CanMessage.
static CanState getData_int16(const CanMessage *msg, int16_t *data);
/// \brief Get an unsigned 16-bit integer from a CanMessage.
static CanState getData_uint16(const CanMessage *msg, uint16_t *data);
/// \brief Get a signed 32-bit integer from a CanMessage.
static CanState getData_int32(const CanMessage *msg, int32_t *data);
/// \brief Get an unsigned 32-bit integer from a CanMessage.
static CanState getData_uint32(const CanMessage *msg, uint32_t *data);
/// \brief Get an array of signed 8-bit integers from a CanMessage.
static CanState getDataArr_int8(const CanMessage *msg, int8_t data[7], uint8_t *len);
/// \brief Get an array of unsigned 8-bit integers from a CanMessage.
static CanState getDataArr_uint8(const CanMessage *msg, uint8_t data[7], uint8_t *len);
/// \brief Get an array of signed 16-bit integers from a CanMessage.
static CanState getDataArr_int16(const CanMessage *msg, int16_t data[3], uint8_t *len);
/// \brief Get an array of unsigned 16-bit integers from a CanMessage.
static CanState getDataArr_uint16(const CanMessage *msg, uint16_t data[3], uint8_t *len);
//@}
/**
* \anchor infoFunctions
* \name Info Functions
* These functions handle names for the \ref CanNode_Module library. They
* allow for providing a name and descriptive text for a node and requesting
* the same information from another node.
* @{
*/
/// \brief Set the name string
void setName(const char *name);
/// \brief Set the info string
void setInfo(const char *info);
/// \brief request the name string from another CanNode
static void requestName(CanNodeType id, char *buff, uint8_t len,
uint16_t timeout);
/// \brief request the info string from another CanNode
static void requestInfo(CanNodeType id, char *buff, uint8_t len,
uint16_t timeout);
// private functions to handle CanNode name functions
/**
* private function to send a node's name string on the CAN bus
*
* \param[in] node CanNode whose information should be sent
*/
void sendName();
/**
* private function to send a node's info string on the CAN bus
*
* \param[in] node CanNode whose information should be sent
*/
void sendInfo();
/// \brief Get a string
static void getString(uint16_t id, char *buff, uint8_t len, uint8_t timeout);
/// \brief Send a string
static void sendString(uint16_t id, const char *str);
};
#endif //_CAN_NODE_H_