LIN_slave_portable_Arduino 1.4
Arduino library for Local Interconnect Network slave node emulation
Loading...
Searching...
No Matches
LIN_slave_Base.cpp
Go to the documentation of this file.
1
10// include files
11#include <LIN_slave_Base.h>
12
13// warn if debug is active (any debug level)
14#if defined(LIN_SLAVE_DEBUG_SERIAL)
15 #warning Debug interface is active, see file 'LIN_slave_Base.h'
16#endif
17
18
19
20/**************************
21 * PROTECTED METHODS
22**************************/
23
31{
32 uint8_t pid; // protected frame ID
33 uint8_t tmp; // temporary variable for calculating parity bits
34
35 // protect ID with parity bits
36 pid = (uint8_t) (ID & 0x3F); // clear upper bits 6 & 7
37 tmp = (uint8_t) ((pid ^ (pid>>1) ^ (pid>>2) ^ (pid>>4)) & 0x01); // pid[6] = PI0 = ID0^ID1^ID2^ID4
38 pid |= (uint8_t) (tmp << 6);
39 tmp = (uint8_t) (~((pid>>1) ^ (pid>>3) ^ (pid>>4) ^ (pid>>5)) & 0x01); // pid[7] = PI1 = ~(ID1^ID3^ID4^ID5)
40 pid |= (uint8_t) (tmp << 7);
41
42 // return protected ID
43 return pid;
44
45} // LIN_Slave_Base::_calculatePID()
46
47
48
56uint8_t LIN_Slave_Base::_calculateChecksum(uint8_t NumData, uint8_t Data[])
57{
58 uint16_t chk=0x00;
59
60 // LIN2.x uses extended checksum which includes protected ID, i.e. including parity bits
61 // LIN1.x uses classical checksum only over data bytes
62 // Diagnostic frames with ID 0x3C and 0x3D/0x7D always use classical checksum (see LIN spec "2.3.1.5 Checkum")
63 if (!((this->version == LIN_V1) || (pid == 0x3C) || (pid == 0x7D))) // if version 2 & no diagnostic frames (0x3C=60 (PID=0x3C) or 0x3D=61 (PID=0x7D))
64 chk = (uint16_t) this->pid;
65
66 // loop over data bytes
67 for (uint8_t i = 0; i < NumData; i++)
68 {
69 chk += (uint16_t) (Data[i]);
70 if (chk>255)
71 chk -= 255;
72 }
73 chk = (uint8_t)(0xFF - ((uint8_t) chk)); // bitwise invert
74
75 // return frame checksum
76 return (uint8_t) chk;
77
78 // optional debug output (debug level 2)
79 #if defined(LIN_SLAVE_DEBUG_SERIAL) && (LIN_SLAVE_DEBUG_LEVEL >= 2)
80 LIN_SLAVE_DEBUG_SERIAL.print(this->nameLIN);
81 LIN_SLAVE_DEBUG_SERIAL.println(": LIN_Slave_Base::_calculateChecksum()");
82 #endif
83
84} // LIN_Slave_Base::_calculateChecksum()
85
86
87
94{
95 // dummy for base class
96 return false;
97
98} // LIN_Slave_Base::_getBreakFlag()
99
100
101
107{
108 // dummy for base class
109
110} // LIN_Slave_Base::_resetBreakFlag()
111
112
113
114/**************************
115 * PUBLIC METHODS
116**************************/
117
127LIN_Slave_Base::LIN_Slave_Base(LIN_Slave_Base::version_t Version, const char NameLIN[], uint32_t TimeoutRx, const int8_t PinTxEN)
128{
129 // Debug serial initialized in begin() -> no debug output here
130
131 // store parameters in class variables
132 this->version = Version; // LIN protocol version (required for checksum)
133 memcpy(this->nameLIN, NameLIN, LIN_SLAVE_BUFLEN_NAME); // node name e.g. for debug
134 this->timeoutRx = TimeoutRx; // timeout [us] for bytes in frame
135 this->pinTxEN = PinTxEN; // optional Tx enable pin for RS485
136
137 // initialize slave node properties
138 this->state = LIN_Slave_Base::STATE_WAIT_FOR_BREAK; // status of LIN state machine
139 this->error = LIN_Slave_Base::NO_ERROR; // last LIN error. Is latched
140 for (uint8_t i=0; i<64; i++)
141 {
142 this->callback[i].type_numData = 0x00; // frame type (high nibble) and number of data bytes (low nibble)
143 this->callback[i].fct = nullptr; // user callback functions (IDs 0x00 - 0x3F)
144 }
145
146 // initialize frame properties
147 this->pid = 0x00; // protected frame identifier
148 this->id = 0x00; // unprotected frame identifier
149 this->numData = 0; // number of data bytes in frame
150 for (uint8_t i=0; i<9; i++)
151 this->bufData[i] = 0x00; // init data bytes (max 8B) + chk
152 this->idxData = 0; // current index in bufData
153 this->timeLastRx = 0; // time [ms] of last received byte in frame
154
155 // initialize TxEN pin low (=transmitter off)
156 if (this->pinTxEN >= 0)
157 {
158 digitalWrite(this->pinTxEN, LOW);
159 pinMode(this->pinTxEN, OUTPUT);
160 }
161
162} // LIN_Slave_Base::LIN_Slave_Base()
163
164
165
171void LIN_Slave_Base::begin(uint16_t Baudrate)
172{
173 // For optional debugging
174 #if defined(LIN_SLAVE_DEBUG_SERIAL)
175 LIN_SLAVE_DEBUG_SERIAL.begin(115200);
176 while (!LIN_SLAVE_DEBUG_SERIAL);
177 #endif
178
179 // print debug message (debug level 2)
180 #if defined(LIN_SLAVE_DEBUG_SERIAL) && (LIN_SLAVE_DEBUG_LEVEL >= 2)
181 LIN_SLAVE_DEBUG_SERIAL.print(this->nameLIN);
182 LIN_SLAVE_DEBUG_SERIAL.print(": LIN_Slave_Base::begin(");
183 LIN_SLAVE_DEBUG_SERIAL.print((int) Baudrate);
184 LIN_SLAVE_DEBUG_SERIAL.println(")");
185 #endif
186
187 // store parameters in class variables
188 this->baudrate = Baudrate; // communication baudrate [Baud]
189
190 // initialize slave node properties
191 this->error = LIN_Slave_Base::NO_ERROR; // last LIN error. Is latched
192 this->state = LIN_Slave_Base::STATE_WAIT_FOR_BREAK; // status of LIN state machine
193
194 // initialize optional TxEN pin to low (=transmitter off)
195 if (this->pinTxEN >= 0)
196 {
197 digitalWrite(this->pinTxEN, LOW);
198 pinMode(this->pinTxEN, OUTPUT);
199 }
200
201} // LIN_Slave_Base::begin()
202
203
204
210{
211 // optional debug output (debug level 2)
212 #if defined(LIN_SLAVE_DEBUG_SERIAL) && (LIN_SLAVE_DEBUG_LEVEL >= 2)
213 LIN_SLAVE_DEBUG_SERIAL.print(this->nameLIN);
214 LIN_SLAVE_DEBUG_SERIAL.println(": LIN_Slave_Base::end()");
215 #endif
216
217 // set slave node properties
218 this->error = LIN_Slave_Base::NO_ERROR; // last LIN error. Is latched
219 this->state = LIN_Slave_Base::STATE_OFF; // status of LIN state machine
220
221 // optionally disable RS485 transmitter
223
224} // LIN_Slave_Base::end()
225
226
227
236{
237 // drop parity bits -> non-protected ID = 0..63
238 ID &= 0x3F;
239
240 // register user callback function for master request frame
241 this->callback[ID].type_numData = LIN_Slave_Base::MASTER_REQUEST | (NumData & 0x0F);
242 this->callback[ID].fct = Fct;
243
244 // optional debug output (debug level 2)
245 #if defined(LIN_SLAVE_DEBUG_SERIAL) && (LIN_SLAVE_DEBUG_LEVEL >= 2)
246 LIN_SLAVE_DEBUG_SERIAL.print(this->nameLIN);
247 LIN_SLAVE_DEBUG_SERIAL.print(": LIN_Slave_Base::registerMasterRequestHandler()");
248 LIN_SLAVE_DEBUG_SERIAL.print(": registered ID 0x");
249 LIN_SLAVE_DEBUG_SERIAL.println(ID, HEX);
250 #endif
251
252} // LIN_Slave_Base::registerMasterRequestHandler
253
254
255
264{
265 // drop parity bits -> non-protected ID = 0..63
266 ID &= 0x3F;
267
268 // register user callback function for slave response frame
269 this->callback[ID].type_numData = LIN_Slave_Base::SLAVE_RESPONSE | (NumData & 0x0F);
270 this->callback[ID].fct = Fct;
271
272 // optional debug output (debug level 2)
273 #if defined(LIN_SLAVE_DEBUG_SERIAL) && (LIN_SLAVE_DEBUG_LEVEL >= 2)
274 LIN_SLAVE_DEBUG_SERIAL.print(this->nameLIN);
275 LIN_SLAVE_DEBUG_SERIAL.print(": LIN_Slave_Base::registerSlaveResponseHandler()");
276 LIN_SLAVE_DEBUG_SERIAL.print(": registered ID 0x");
277 LIN_SLAVE_DEBUG_SERIAL.println(ID, HEX);
278 #endif
279
280} // LIN_Slave_Base::registerSlaveResponseHandler
281
282
283
289{
290 uint8_t chk_calc;
291
292 // on receive timeout [us] within frame reset state machine
294 ((micros() - this->timeLastRx) > this->timeoutRx))
295 {
296 // set error and abort frame
299
300 // flush receive buffer
301 while (this->available())
302 this->_serialRead();
303
304 // optionally disable RS485 transmitter
306
307 // optional debug output (debug level 1)
308 #if defined(LIN_SLAVE_DEBUG_SERIAL) && (LIN_SLAVE_DEBUG_LEVEL >= 1)
309 LIN_SLAVE_DEBUG_SERIAL.print(this->nameLIN);
310 LIN_SLAVE_DEBUG_SERIAL.print(": LIN_Slave_Base::handler()");
311 LIN_SLAVE_DEBUG_SERIAL.print(": error: frame timeout after ");
312 LIN_SLAVE_DEBUG_SERIAL.print((long) (micros() - this->timeLastRx));
313 LIN_SLAVE_DEBUG_SERIAL.println("us");
314 #endif
315
316 } // if frame receive timeout
317
318
319 // detected LIN BREAK (=0x00 with framing error or inter-frame pause detected)
320 // Note: received BREAK byte is consumed by child class to support also sync on SYNC byte.
321 if (this->_getBreakFlag() == true)
322 {
323 // clear BREAK flag again
324 this->_resetBreakFlag();
325
326 // start frame reception. Note: 0x00 already checked by derived class
328
329 // optionally disable RS485 transmitter
331
332 // optional debug output (debug level 3)
333 #if defined(LIN_SLAVE_DEBUG_SERIAL) && (LIN_SLAVE_DEBUG_LEVEL >= 3)
334 LIN_SLAVE_DEBUG_SERIAL.print(this->nameLIN);
335 LIN_SLAVE_DEBUG_SERIAL.print(": LIN_Slave_Base::handler()");
336 LIN_SLAVE_DEBUG_SERIAL.println(": BREAK detected ");
337 #endif
338
339 } // if BREAK detected
340
341
342 // A byte was received -> handle it
343 if (this->available())
344 {
345 // read received byte and reset timeout timer
346 uint8_t byteReceived = this->_serialRead();
347 this->timeLastRx = micros();
348
349 // optional debug output (debug level 3)
350 #if defined(LIN_SLAVE_DEBUG_SERIAL) && (LIN_SLAVE_DEBUG_LEVEL >= 3)
351 LIN_SLAVE_DEBUG_SERIAL.print(this->nameLIN);
352 LIN_SLAVE_DEBUG_SERIAL.print(": LIN_Slave_Base::handler()");
353 if (this->_getBreakFlag() == true)
354 LIN_SLAVE_DEBUG_SERIAL.print(": BRK, Rx=0x");
355 else
356 LIN_SLAVE_DEBUG_SERIAL.print(": Rx=0x");
357 LIN_SLAVE_DEBUG_SERIAL.println(byteReceived, HEX);
358 #endif
359
360 // handle byte
361 switch (this->state)
362 {
363 // LIN interface disabled, do nothing
365 break;
366
367 // just to avoid compiler warning, do nothing. Break state is handled above
369 break;
370
371 // master request frame is finished, do nothing
373 break;
374
375 // break has been received, waiting for sync field
377
378 // valid SYNC (=0x55) -> wait for ID
379 if (byteReceived == 0x55)
380 {
381 this->idxData = 0;
383 }
384
385 // invalid SYNC (!=0x55) -> error
386 else
387 {
388 // set error and abort frame
389 this->error = (LIN_Slave_Base::error_t) ((int) this->error | (int) LIN_Slave_Base::ERROR_SYNC);
391
392 // optionally disable RS485 transmitter
394
395 // optional debug output (debug level 1)
396 #if defined(LIN_SLAVE_DEBUG_SERIAL) && (LIN_SLAVE_DEBUG_LEVEL >= 1)
397 LIN_SLAVE_DEBUG_SERIAL.print(this->nameLIN);
398 LIN_SLAVE_DEBUG_SERIAL.print(": LIN_Slave_Base::handler()");
399 LIN_SLAVE_DEBUG_SERIAL.print(": SYNC error, received 0x");
400 LIN_SLAVE_DEBUG_SERIAL.println(byteReceived, HEX);
401 #endif
402
403 } // invalid SYNC
404
405 break; // STATE_WAIT_FOR_SYNC
406
407
408 // sync field has been received, waiting for protected ID
410
411 this->pid = byteReceived; // received (protected) ID
412 this->id = byteReceived & 0x3F; // extract ID, drop parity bits
413
414 // check PID parity bits 7+8
415 if (this->pid != this->_calculatePID(this->id))
416 {
417 // set error and abort frame
418 this->error = (LIN_Slave_Base::error_t) ((int) this->error | (int) LIN_Slave_Base::ERROR_PID);
420
421 // optionally disable RS485 transmitter
423
424 // optional debug output (debug level 1)
425 #if defined(LIN_SLAVE_DEBUG_SERIAL) && (LIN_SLAVE_DEBUG_LEVEL >= 1)
426 LIN_SLAVE_DEBUG_SERIAL.print(this->nameLIN);
427 LIN_SLAVE_DEBUG_SERIAL.print(": LIN_Slave_Base::handler()");
428 LIN_SLAVE_DEBUG_SERIAL.print(": PID parity error, received 0x");
429 LIN_SLAVE_DEBUG_SERIAL.print(this->pid, HEX);
430 LIN_SLAVE_DEBUG_SERIAL.print(", calculated 0x");
431 LIN_SLAVE_DEBUG_SERIAL.println(this->_calculatePID(this->id), HEX);
432 #endif
433
434 } // PID error
435
436 // if slave response ID is registered, call callback function and send response
437 else if ((this->callback[id].fct != nullptr) && (this->callback[id].type_numData & LIN_Slave_Base::SLAVE_RESPONSE))
438 {
439 // get type (high nibble) and number of response bytes (low nibble) from callback array
440 this->type = (LIN_Slave_Base::frame_t) (this->callback[id].type_numData & 0xF0);
441 this->numData = this->callback[id].type_numData & 0x0F;
442
443 // call the user-defined callback function for this ID
444 this->callback[id].fct(numData, this->bufData);
445
446 // attach frame checksum
447 bufData[numData] = this->_calculateChecksum(this->numData, this->bufData);
448
449 // optionally enable RS485 transmitter
451
452 // send slave response (data+chk)
453 this->_serialWrite(bufData, numData+1);
454
455 // advance state to receiving echo
457
458 // optional debug output (debug level 2)
459 #if defined(LIN_SLAVE_DEBUG_SERIAL) && (LIN_SLAVE_DEBUG_LEVEL >= 2)
460 LIN_SLAVE_DEBUG_SERIAL.print(this->nameLIN);
461 LIN_SLAVE_DEBUG_SERIAL.print(": LIN_Slave_Base::handler()");
462 LIN_SLAVE_DEBUG_SERIAL.print(": handle slave response PID 0x");
463 LIN_SLAVE_DEBUG_SERIAL.println(this->pid, HEX);
464 #endif
465
466 } // if slave response frame
467
468 // if master request ID is registered, get number of data bytes and advance state
469 else if ((this->callback[id].fct != nullptr) && (this->callback[id].type_numData & LIN_Slave_Base::MASTER_REQUEST))
470 {
471 // get type (high nibble) and number of response bytes (low nibble) from callback array
472 this->type = (LIN_Slave_Base::frame_t) (this->callback[id].type_numData & 0xF0);
473 this->numData = this->callback[id].type_numData & 0x0F;
474
475 // advance state to receiving data
477
478 } // if master request frame
479
480 // ID is not registered -> wait for next break
481 else
482 {
483 // optional debug output (debug level 2)
484 #if defined(LIN_SLAVE_DEBUG_SERIAL) && (LIN_SLAVE_DEBUG_LEVEL >= 2)
485 LIN_SLAVE_DEBUG_SERIAL.print(this->nameLIN);
486 LIN_SLAVE_DEBUG_SERIAL.print(": LIN_Slave_Base::handler()");
487 LIN_SLAVE_DEBUG_SERIAL.print(": drop frame PID 0x");
488 LIN_SLAVE_DEBUG_SERIAL.println(this->pid, HEX);
489 #endif
490
491 // reset state machine
493
494 } // if frame not registered
495
496 break; // STATE_WAIT_FOR_PID
497
498
499 // receive master request data
501
502 // check received data
503 this->bufData[(this->idxData)++] = byteReceived;
504
505 // if data is finished, advance to checksum check
506 if (this->idxData >= this->numData)
508
509 break; // STATE_RECEIVING_DATA
510
511
512 // receive slave response echo
514
515 // compare received echo to sent data
516 if (this->bufData[(this->idxData)++] != byteReceived)
517 {
518 // set error and abort frame
519 this->error = (LIN_Slave_Base::error_t) ((int) this->error | (int) LIN_Slave_Base::ERROR_ECHO);
521
522 // optionally disable RS485 transmitter
524
525 // optional debug output (debug level 1)
526 #if defined(LIN_SLAVE_DEBUG_SERIAL) && (LIN_SLAVE_DEBUG_LEVEL >= 1)
527 LIN_SLAVE_DEBUG_SERIAL.print(this->nameLIN);
528 LIN_SLAVE_DEBUG_SERIAL.print(": LIN_Slave_Base::handler()");
529 LIN_SLAVE_DEBUG_SERIAL.print(": echo error, received 0x");
530 LIN_SLAVE_DEBUG_SERIAL.print(byteReceived, HEX);
531 LIN_SLAVE_DEBUG_SERIAL.print(", expected 0x");
532 LIN_SLAVE_DEBUG_SERIAL.println(this->bufData[(this->idxData)-1], HEX);
533 #endif
534
535 } // if echo error
536
537 // if data is finished, finish frame
538 else if (this->idxData >= this->numData+1)
539 {
541
542 // optionally disable RS485 transmitter
544 }
545
546 break; // STATE_RECEIVING_ECHO
547
548
549 // Data has been received for master request frame, waiting for checksum
551
552 // calculate checksum for master request frame
553 chk_calc = this->_calculateChecksum(this->numData, this->bufData);
554
555 // Checksum valid -> call user-defined callback function for this ID
556 if (byteReceived == chk_calc)
557 {
558 // call user-defined master request callback function. Only reachable if callback has been registered
559 this->callback[id].fct(numData, bufData);
560
561 // optional debug output (debug level 2)
562 #if defined(LIN_SLAVE_DEBUG_SERIAL) && (LIN_SLAVE_DEBUG_LEVEL >= 2)
563 LIN_SLAVE_DEBUG_SERIAL.print(this->nameLIN);
564 LIN_SLAVE_DEBUG_SERIAL.print(": LIN_Slave_Base::handler()");
565 LIN_SLAVE_DEBUG_SERIAL.print(": handle master request PID 0x");
566 LIN_SLAVE_DEBUG_SERIAL.println(this->pid, HEX);
567 #endif
568
569 } // if checksum ok
570
571 // checksum error
572 else
573 {
574 // set error
575 this->error = (LIN_Slave_Base::error_t) ((int) this->error | (int) LIN_Slave_Base::ERROR_CHK);
576
577 // optional debug output (debug level 1)
578 #if defined(LIN_SLAVE_DEBUG_SERIAL) && (LIN_SLAVE_DEBUG_LEVEL >= 1)
579 LIN_SLAVE_DEBUG_SERIAL.print(this->nameLIN);
580 LIN_SLAVE_DEBUG_SERIAL.print(": LIN_Slave_Base::handler()");
581 LIN_SLAVE_DEBUG_SERIAL.print(": CHK error, received 0x");
582 LIN_SLAVE_DEBUG_SERIAL.print(byteReceived, HEX);
583 LIN_SLAVE_DEBUG_SERIAL.print(", calculated 0x");
584 LIN_SLAVE_DEBUG_SERIAL.println(chk_calc, HEX);
585 #endif
586
587 } // if checksum error
588
589 // frame is finished
591
592 // optionally disable RS485 transmitter
594
595 break; // STATE_WAIT_FOR_CHK
596
597
598 // this should never happen -> error
599 default:
600
601 // set error and abort frame
602 this->error = (LIN_Slave_Base::error_t) ((int) this->error | (int) LIN_Slave_Base::LIN_Slave_Base::ERROR_STATE);
604
605 // optionally disable RS485 transmitter
607
608 // optional debug output (debug level 1)
609 #if defined(LIN_SLAVE_DEBUG_SERIAL) && (LIN_SLAVE_DEBUG_LEVEL >= 1)
610 LIN_SLAVE_DEBUG_SERIAL.print(this->nameLIN);
611 LIN_SLAVE_DEBUG_SERIAL.print(": LIN_Slave_Base::handler()");
612 LIN_SLAVE_DEBUG_SERIAL.print(": error: illegal state ");
613 LIN_SLAVE_DEBUG_SERIAL.print(this->state);
614 LIN_SLAVE_DEBUG_SERIAL.println(", this should never happen...");
615 #endif
616
617 } // switch(state)
618
619 } // if byte received
620
621} // LIN_Slave_Base::handler
622
623/*-----------------------------------------------------------------------------
624 END OF FILE
625-----------------------------------------------------------------------------*/
Base class for LIN slave emulation (non-functional)
uint32_t timeLastRx
time [us] of last received byte in frame
uint8_t idxData
current index in bufData
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.
uint16_t baudrate
communication baudrate [Baud]
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
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.
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_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.
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_PID
ID parity error.
@ 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_Slave_Base(LIN_Slave_Base::version_t Version=LIN_Slave_Base::LIN_V2, const char NameLIN[]="Slave", uint32_t TimeoutRx=1500L, const int8_t PinTxEN=INT8_MIN)
LIN slave node constructor.
uint8_t pid
protected frame identifier
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.
uint8_t type_numData
frame type (high nibble) and number of data bytes (low nibble)
LinMessageCallback fct
frame callback function