LIN_slave_portable_Arduino 1.4
Arduino library for Local Interconnect Network slave node emulation
Loading...
Searching...
No Matches
LIN_slave_Base.h
Go to the documentation of this file.
1
10/*-----------------------------------------------------------------------------
11 MODULE DEFINITION FOR MULTIPLE INCLUSION
12-----------------------------------------------------------------------------*/
13#ifndef _LIN_SLAVE_BASE_H_
14#define _LIN_SLAVE_BASE_H_
15
16
17/*-----------------------------------------------------------------------------
18 GLOBAL DEFINES
19-----------------------------------------------------------------------------*/
20
21// misc parameters
22#define LIN_SLAVE_BUFLEN_NAME 30
23
24// optional LIN debug output @ 115.2kBaud. When using together with NeoHWSerial on AVR must use NeoSerialx to avoid linker conflict
25#if !defined(LIN_SLAVE_DEBUG_SERIAL)
26 //#define LIN_SLAVE_DEBUG_SERIAL Serial //!< serial interface used for debug output. Comment out for none
27 //#define LIN_SLAVE_DEBUG_SERIAL NeoSerial //!< serial interface used for debug output (required for AVR). Comment out for none
28 //#include <NeoHWSerial.h> // comment in/out together with previous line
29#endif
30#if !defined(LIN_SLAVE_DEBUG_LEVEL)
31 //#define LIN_SLAVE_DEBUG_LEVEL 2 //!< debug verbosity 0..3 (1=errors only, 3=chatty)
32#endif
33
34/*-----------------------------------------------------------------------------
35 INCLUDE FILES
36-----------------------------------------------------------------------------*/
37
38// generic Arduino functions
39#include <Arduino.h>
40
41
42/*-----------------------------------------------------------------------------
43 GLOBAL CLASS
44-----------------------------------------------------------------------------*/
45
52{
53 // PUBLIC TYPEDEFS
54 public:
55
57 typedef enum : uint8_t
58 {
59 LIN_V1 = 1,
60 LIN_V2 = 2
62
63
65 typedef enum : uint8_t
66 {
68 SLAVE_RESPONSE = 0x20
70
71
84
85
87 typedef enum : uint8_t
88 {
89 NO_ERROR = 0x00,
90 ERROR_STATE = 0x01,
91 ERROR_ECHO = 0x02,
93 ERROR_CHK = 0x08,
94 ERROR_SYNC = 0x10,
95 ERROR_PID = 0x20,
96 ERROR_MISC = 0x80
98
99
100 // PROTECTED TYPEDEFS
101 protected:
102
104 typedef void (*LinMessageCallback)(uint8_t numData, uint8_t* data);
105
107 typedef struct
108 {
109 uint8_t type_numData;
111 } callback_t;
112
113
114 // PROTECTED VARIABLES
115 protected:
116
117 // node properties
118 int8_t pinTxEN;
119 uint16_t baudrate;
125
126 // latest frame properties
127 uint8_t pid;
128 uint8_t id;
130 uint8_t numData;
131 uint8_t bufData[9];
132 uint8_t idxData;
133 uint32_t timeoutRx;
134 uint32_t timeLastRx;
135
136
137 // PUBLIC VARIABLES
138 public:
139
140 char nameLIN[LIN_SLAVE_BUFLEN_NAME];
141
142
143 // PROTECTED METHODS
144 protected:
145
147 uint8_t _calculatePID(uint8_t ID);
148
150 uint8_t _calculateChecksum(uint8_t NumData, uint8_t Data[]);
151
153 virtual bool _getBreakFlag(void);
154
156 virtual void _resetBreakFlag(void);
157
158
160 virtual inline uint8_t _serialPeek(void) { return 0x00; }
161
163 virtual inline uint8_t _serialRead(void) { return 0x00; }
164
166 virtual inline void _serialWrite(uint8_t buf[], uint8_t num) { (void) buf; (void) num; }
167
168
170 inline void _enableTransmitter(void)
171 {
172 // print debug message (debug level 3)
173 #if defined(LIN_SLAVE_DEBUG_SERIAL) && (LIN_SLAVE_DEBUG_LEVEL >= 3)
174 LIN_SLAVE_DEBUG_SERIAL.println("LIN_Slave_Base::_enableTransmitter()");
175 #endif
176
177 // enable tranmitter
178 if (this->pinTxEN >= 0)
179 digitalWrite(this->pinTxEN, HIGH);
180
181 } // _enableTransmitter()
182
184 inline void _disableTransmitter(void)
185 {
186 // print debug message (debug level 3)
187 #if defined(LIN_SLAVE_DEBUG_SERIAL) && (LIN_SLAVE_DEBUG_LEVEL >= 3)
188 LIN_SLAVE_DEBUG_SERIAL.println("LIN_Slave_Base::_disableTransmitter()");
189 #endif
190
191 // disable tranmitter
192 if (this->pinTxEN >= 0)
193 digitalWrite(this->pinTxEN, LOW);
194
195 } // _disableTransmitter()
196
197
198 // PUBLIC METHODS
199 public:
200
202 LIN_Slave_Base(LIN_Slave_Base::version_t Version = LIN_Slave_Base::LIN_V2, const char NameLIN[] = "Slave",
203 uint32_t TimeoutRx = 1500L, const int8_t PinTxEN = INT8_MIN);
204
206 virtual ~LIN_Slave_Base(void) {};
207
208
210 virtual void begin(uint16_t Baudrate = 19200);
211
213 virtual void end(void);
214
216 virtual inline bool available(void) { return false; }
217
218
220 inline void resetStateMachine(void)
221 {
222 // print debug message (debug level 3)
223 #if defined(LIN_SLAVE_DEBUG_SERIAL) && (LIN_SLAVE_DEBUG_LEVEL >= 3)
224 LIN_SLAVE_DEBUG_SERIAL.println("LIN_Slave_Base::resetStateMachine()");
225 #endif
226
227 // reset state
229
230 } // resetStateMachine()
231
234 {
235 // print debug message (debug level 3)
236 #if defined(LIN_SLAVE_DEBUG_SERIAL) && (LIN_SLAVE_DEBUG_LEVEL >= 3)
237 LIN_SLAVE_DEBUG_SERIAL.println("LIN_Slave_Base::getState()");
238 #endif
239
240 // return state
241 return this->state;
242
243 } // getState()
244
245
247 inline void resetError(void)
248 {
249 // print debug message (debug level 3)
250 #if defined(LIN_SLAVE_DEBUG_SERIAL) && (LIN_SLAVE_DEBUG_LEVEL >= 3)
251 LIN_SLAVE_DEBUG_SERIAL.println("LIN_Slave_Base::resetError()");
252 #endif
253
254 // reset error
255 this->error = LIN_Slave_Base::NO_ERROR;
256
257 } // resetError()
258
261 {
262 // print debug message (debug level 3)
263 #if defined(LIN_SLAVE_DEBUG_SERIAL) && (LIN_SLAVE_DEBUG_LEVEL >= 3)
264 LIN_SLAVE_DEBUG_SERIAL.println("LIN_Slave_Base::getError()");
265 #endif
266
267 // return error
268 return this->error;
269
270 } // getError()
271
272
274 inline void getFrame(LIN_Slave_Base::frame_t &Type, uint8_t &Id, uint8_t &NumData, uint8_t Data[])
275 {
276 // print debug message (debug level 3)
277 #if defined(LIN_SLAVE_DEBUG_SERIAL) && (LIN_SLAVE_DEBUG_LEVEL >= 3)
278 LIN_SLAVE_DEBUG_SERIAL.println("LIN_Slave_Base::getFrame()");
279 #endif
280
281 noInterrupts(); // for data consistency temporarily disable ISRs
282 Type = this->type; // frame type
283 Id = this->id; // frame ID
284 NumData = this->numData; // number of data bytes (excl. BREAK, SYNC, ID, CHK)
285 memcpy(Data, this->bufData, NumData); // copy data bytes w/o checksum
286 interrupts(); // re-enable ISRs
287
288 } // getFrame()
289
290
292 void registerMasterRequestHandler(uint8_t ID, LIN_Slave_Base::LinMessageCallback Fct, uint8_t NumData);
293
295 void registerSlaveResponseHandler(uint8_t ID, LIN_Slave_Base::LinMessageCallback Fct, uint8_t NumData);
296
297
299 virtual void handler(void);
300
301}; // class LIN_Slave_Base
302
303/*-----------------------------------------------------------------------------
304 END OF MODULE DEFINITION FOR MULTIPLE INLUSION
305-----------------------------------------------------------------------------*/
306#endif // _LIN_SLAVE_BASE_H_
307
308/*-----------------------------------------------------------------------------
309 END OF FILE
310-----------------------------------------------------------------------------*/
LIN slave node base class.
uint32_t timeLastRx
time [us] of last received byte in frame
uint8_t idxData
current index in bufData
bool flagBreak
flag for BREAK detected. Needs to be set in Rx-ISR
LIN_Slave_Base::error_t error
error state. Is latched until cleared
void registerSlaveResponseHandler(uint8_t ID, LIN_Slave_Base::LinMessageCallback Fct, uint8_t NumData)
Attach user callback function for slave response frame.
void getFrame(LIN_Slave_Base::frame_t &Type, uint8_t &Id, uint8_t &NumData, uint8_t Data[])
Getter for LIN frame.
uint16_t baudrate
communication baudrate [Baud]
void resetStateMachine(void)
Reset LIN state machine.
virtual void _serialWrite(uint8_t buf[], uint8_t num)
write bytes to Tx buffer. Here dummy
int8_t pinTxEN
optional Tx direction pin, e.g. for LIN via RS485
virtual ~LIN_Slave_Base(void)
LIN slave node destructor, here dummy. Any class with virtual functions should have virtual destructo...
frame_t
LIN frame type. Use high nibble for type, low nibble for number of data bytes -> minimize callback[] ...
@ SLAVE_RESPONSE
LIN slave response frame.
@ MASTER_REQUEST
LIN master request frame.
virtual uint8_t _serialPeek(void)
peek next byte from Rx buffer. Here dummy
uint8_t bufData[9]
buffer for data bytes (max. 8B) + checksum
uint32_t timeoutRx
timeout [us] for bytes in frame
virtual bool _getBreakFlag(void)
Get break detection flag. Is hardware dependent.
uint8_t numData
number of data bytes in frame
LIN_Slave_Base::frame_t type
frame type (master request or slave response)
state_t
LIN state machine states. Use bitmasks for fast checking multiple states.
@ STATE_DONE
frame is completed
@ STATE_WAIT_FOR_PID
SYNC received, wait for frame PID.
@ STATE_OFF
LIN interface closed.
@ STATE_WAIT_FOR_BREAK
no LIN transmission ongoing, wait for BRK
@ STATE_WAIT_FOR_SYNC
BRK received, wait for SYNC.
@ STATE_RECEIVING_ECHO
receiving slave response echo
@ STATE_RECEIVING_DATA
receiving master request data
@ STATE_WAIT_FOR_CHK
waiting for checksum
LIN_Slave_Base::version_t version
LIN protocol version.
uint8_t id
unprotected frame identifier
void _disableTransmitter(void)
Disable RS485 transmitter (DE=low)
virtual void begin(uint16_t Baudrate=19200)
Open serial interface.
void registerMasterRequestHandler(uint8_t ID, LIN_Slave_Base::LinMessageCallback Fct, uint8_t NumData)
Attach user callback function for master request frame.
LIN_Slave_Base::state_t getState(void)
Getter for LIN state machine state.
error_t
LIN error codes. Use bitmasks, as error is latched. Use same as LIN_master_portable.
@ ERROR_SYNC
error in SYNC (not 0x55)
@ ERROR_TIMEOUT
frame timeout error
@ ERROR_ECHO
error reading response echo
@ ERROR_STATE
error in LIN state machine
@ ERROR_PID
ID parity error.
@ ERROR_MISC
misc error, should not occur
@ ERROR_CHK
LIN checksum error.
@ NO_ERROR
no error
virtual uint8_t _serialRead(void)
read next byte from Rx buffer. Here dummy
uint8_t _calculateChecksum(uint8_t NumData, uint8_t Data[])
Calculate LIN frame checksum.
char nameLIN[LIN_SLAVE_BUFLEN_NAME]
LIN node name, e.g. for debug.
void(* LinMessageCallback)(uint8_t numData, uint8_t *data)
Type for frame callback function.
uint8_t _calculatePID(uint8_t ID)
Calculate protected frame ID.
virtual void _resetBreakFlag(void)
Clear break detection flag. Is hardware dependent.
version_t
LIN protocol version.
@ LIN_V1
LIN protocol version 1.x.
@ LIN_V2
LIN protocol version 2.x.
void resetError(void)
Clear error of LIN state machine.
uint8_t pid
protected frame identifier
LIN_Slave_Base::error_t getError(void)
Getter for LIN state machine error.
LIN_Slave_Base::state_t state
status of LIN state machine
void _enableTransmitter(void)
Enable RS485 transmitter (DE=high)
virtual void end(void)
Close serial interface.
virtual bool available(void)
check if a byte is available in Rx buffer. Here dummy
LIN_Slave_Base::callback_t callback[64]
array of user callback functions for IDs 0x00..0x3F
virtual void handler(void)
Handle LIN protocol and call user-defined frame callbacks.
User-defined callback function with data length.
uint8_t type_numData
frame type (high nibble) and number of data bytes (low nibble)
LinMessageCallback fct
frame callback function