14#if defined(LIN_SLAVE_DEBUG_SERIAL)
15 #warning Debug interface is active, see file 'LIN_slave_Base.h'
36 pid = (uint8_t) (ID & 0x3F);
37 tmp = (uint8_t) ((
pid ^ (
pid>>1) ^ (
pid>>2) ^ (
pid>>4)) & 0x01);
38 pid |= (uint8_t) (tmp << 6);
39 tmp = (uint8_t) (~((
pid>>1) ^ (
pid>>3) ^ (
pid>>4) ^ (
pid>>5)) & 0x01);
40 pid |= (uint8_t) (tmp << 7);
64 chk = (uint16_t) this->
pid;
67 for (uint8_t i = 0; i < NumData; i++)
69 chk += (uint16_t) (Data[i]);
73 chk = (uint8_t)(0xFF - ((uint8_t) chk));
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()");
133 memcpy(this->
nameLIN, NameLIN, LIN_SLAVE_BUFLEN_NAME);
140 for (uint8_t i=0; i<64; i++)
150 for (uint8_t i=0; i<9; i++)
158 digitalWrite(this->
pinTxEN, LOW);
159 pinMode(this->
pinTxEN, OUTPUT);
174 #if defined(LIN_SLAVE_DEBUG_SERIAL)
175 LIN_SLAVE_DEBUG_SERIAL.begin(115200);
176 while (!LIN_SLAVE_DEBUG_SERIAL);
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(
")");
197 digitalWrite(this->
pinTxEN, LOW);
198 pinMode(this->
pinTxEN, OUTPUT);
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()");
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);
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);
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");
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 ");
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()");
354 LIN_SLAVE_DEBUG_SERIAL.print(
": BRK, Rx=0x");
356 LIN_SLAVE_DEBUG_SERIAL.print(
": Rx=0x");
357 LIN_SLAVE_DEBUG_SERIAL.println(byteReceived, HEX);
379 if (byteReceived == 0x55)
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);
411 this->
pid = byteReceived;
412 this->
id = byteReceived & 0x3F;
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);
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);
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);
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);
556 if (byteReceived == chk_calc)
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);
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);
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...");
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.
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