/* * LinFrame.h * * Created on: 26 дек. 2015 г. * Author: esaulenko */ #ifndef DRIVERS_LIN_LINFRAME_H_ #define DRIVERS_LIN_LINFRAME_H_ #include #include "Utils.h" class TLinFrame { private: enum { MaxDataLen = 16, }; public: TLinFrame(): data_len(-1) // изначально буфер пустой {} uint8_t id; int8_t data_len; // знак используется при приёме uint16_t data[MaxDataLen + 1]; // data + chksum // посчитать контрольную сумму по стандарту 1.1 (без ID) или по стандарту 2.0 (c ID) uint8_t CalcChksum (bool new_mode) { data_len = MIN (data_len, MaxDataLen); uint32_t chksum = new_mode ? id : 0; for (int i = 0; i < data_len; i++) { chksum += data[i]; if (chksum > 0xFF) chksum -= 0xFF; } return ~ chksum; } // добавить контрольную сумму в пакет void AddChksum (bool new_mode) { data[data_len] = CalcChksum (new_mode); } // проверить контрольную сумму пакета bool IsChksumCorrect (bool new_mode) { return data[data_len] == CalcChksum (new_mode); } // посчитать контрольные (старшие) биты в идентификаторе void CalcIdChksum (uint8_t aId) { // byte = p7 p6 b5..b0 // P6 = b0 ^ b1 ^ b2 ^ b4 // P7 = ~ (b1 ^ b3 ^ b4 ^ b5) uint8_t P6 = (aId >> 0) ^ (aId >> 1) ^ (aId >> 2) ^ (aId >> 4); uint8_t P7 = (aId >> 1) ^ (aId >> 3) ^ (aId >> 4) ^ (aId >> 5); P6 = ( P6 & 0x01) << 6; P7 = ((~P7) & 0x01) << 7; id = P7 | P6 | (aId & 0x3F); } // скопировать данные в кадр (до 8 байт) template inline void SetData (const char (&data_str)[N]) { data_len = MIN (N - 1, MaxDataLen); for (int i = 0; i < data_len; i++) data[i] = (uint8_t)data_str[i]; } }; #endif /* DRIVERS_LIN_LINFRAME_H_ */