LIN: Legacy API

pull/56/head
Kyle Johannes 2023-04-05 15:43:26 +00:00
parent 0fa7494eab
commit 63c81b1c3d
17 changed files with 1134 additions and 104 deletions

View File

@ -73,6 +73,25 @@ static bool NeoMessageToSpyMessage(const neodevice_t* device, const neomessage_t
return false; return false;
const neomessage_frame_t& frame = *reinterpret_cast<const neomessage_frame_t*>(&newmsg); const neomessage_frame_t& frame = *reinterpret_cast<const neomessage_frame_t*>(&newmsg);
auto copyStatusData = [&]() {
oldmsg.NetworkID = static_cast<uint8_t>(frame.netid); // Note: NetID remapping from the original API is not supported
oldmsg.NetworkID2 = static_cast<uint8_t>(frame.netid >> 8);
oldmsg.DescriptionID = frame.description;
oldmsg.StatusBitField = frame.status.statusBitfield[0];
oldmsg.StatusBitField2 = frame.status.statusBitfield[1];
oldmsg.StatusBitField3 = frame.status.statusBitfield[2];
oldmsg.StatusBitField4 = frame.status.statusBitfield[3];
};
auto copyFrameData = [&]() {
oldmsg.ExtraDataPtr = (void*)frame.data;
oldmsg.ExtraDataPtrEnabled = frame.length > 8 ? 1 : 0;
memcpy(oldmsg.Data, frame.data, std::min(frame.length, (size_t)8));
oldmsg.ArbIDOrHeader = *reinterpret_cast<const uint32_t*>(frame.header);
copyStatusData();
};
switch (Network::Type(frame.type)) switch (Network::Type(frame.type))
{ {
case Network::Type::CAN: case Network::Type::CAN:
@ -81,28 +100,42 @@ static bool NeoMessageToSpyMessage(const neodevice_t* device, const neomessage_t
oldmsg.Protocol = frame.status.canfdFDF ? SPY_PROTOCOL_CANFD : SPY_PROTOCOL_CAN; oldmsg.Protocol = frame.status.canfdFDF ? SPY_PROTOCOL_CANFD : SPY_PROTOCOL_CAN;
oldmsg.NumberBytesData = static_cast<uint8_t>(std::min(frame.length, (size_t)255)); oldmsg.NumberBytesData = static_cast<uint8_t>(std::min(frame.length, (size_t)255));
oldmsg.NumberBytesHeader = 4; oldmsg.NumberBytesHeader = 4;
copyFrameData();
break; break;
case Network::Type::Ethernet: case Network::Type::Ethernet:
oldmsg.Protocol = SPY_PROTOCOL_ETHERNET; oldmsg.Protocol = SPY_PROTOCOL_ETHERNET;
oldmsg.NumberBytesData = static_cast<uint8_t>(frame.length & 0xFF); oldmsg.NumberBytesData = static_cast<uint8_t>(frame.length & 0xFF);
oldmsg.NumberBytesHeader = static_cast<uint8_t>(frame.length >> 8); oldmsg.NumberBytesHeader = static_cast<uint8_t>(frame.length >> 8);
copyFrameData();
break; break;
case Network::Type::LIN:
{
const neomessage_lin_t& linFrame = *reinterpret_cast<const neomessage_lin_t*>(&frame);
icsSpyMessageJ1850& linSpyMsg = *reinterpret_cast<icsSpyMessageJ1850*>(&oldmsg);
linSpyMsg.Protocol = SPY_PROTOCOL_LIN;
linSpyMsg.NumberBytesHeader = static_cast<uint8_t>(std::min(linFrame.length, static_cast<size_t>(3)));
linSpyMsg.NumberBytesData = static_cast<uint8_t>(linFrame.length - linSpyMsg.NumberBytesHeader);
oldmsg.ArbIDOrHeader = *reinterpret_cast<const uint32_t*>(frame.header);
copyStatusData();
if ((2 < linFrame.length) && (linFrame.length <= 10)) {
auto copyBytes = std::min(linSpyMsg.NumberBytesData, static_cast<uint8_t>(6));
std::memcpy(oldmsg.Data, frame.data, copyBytes);
oldmsg.Data[copyBytes] = linFrame.checksum;
} else if (2 == linFrame.length) {
std::memset(oldmsg.Data, 0, 8);
linSpyMsg.Header[linSpyMsg.NumberBytesHeader] = linFrame.checksum;
++linSpyMsg.NumberBytesHeader;
} else {
std::memset(oldmsg.Data, 0, 8);
}
if (linFrame.linStatus.txCommander)
linSpyMsg.StatusBitField |= SPY_STATUS_INIT_MESSAGE;
break;
}
default: default:
return false; return false;
} }
oldmsg.ExtraDataPtr = (void*)frame.data;
oldmsg.ExtraDataPtrEnabled = frame.length > 8 ? 1 : 0;
memcpy(oldmsg.Data, frame.data, std::min(frame.length, (size_t)8));
oldmsg.ArbIDOrHeader = *reinterpret_cast<const uint32_t*>(frame.header);
oldmsg.NetworkID = static_cast<uint8_t>(frame.netid); // Note: NetID remapping from the original API is not supported
oldmsg.NetworkID2 = static_cast<uint8_t>(frame.netid >> 8);
oldmsg.DescriptionID = frame.description;
oldmsg.StatusBitField = frame.status.statusBitfield[0];
oldmsg.StatusBitField2 = frame.status.statusBitfield[1];
oldmsg.StatusBitField3 = frame.status.statusBitfield[2];
oldmsg.StatusBitField4 = frame.status.statusBitfield[3];
// Timestamp - epoch = 1/1/2007 - 25ns per tick most of the time // Timestamp - epoch = 1/1/2007 - 25ns per tick most of the time
uint64_t t = frame.timestamp; uint64_t t = frame.timestamp;
uint16_t res = 0; uint16_t res = 0;
@ -127,6 +160,84 @@ static bool NeoMessageToSpyMessage(const neodevice_t* device, const neomessage_t
return true; return true;
} }
static bool SpyMessageToNeoMessage(const icsSpyMessage& oldmsg, neomessage_frame_t& frame, unsigned int& lNetworkID)
{
frame.netid = static_cast<uint16_t>(lNetworkID);
frame.description = oldmsg.DescriptionID;
frame.status.statusBitfield[0] = oldmsg.StatusBitField;
frame.status.statusBitfield[1] = oldmsg.StatusBitField2;
frame.status.statusBitfield[2] = oldmsg.StatusBitField3;
frame.status.statusBitfield[3] = oldmsg.StatusBitField4;
auto copyFrameDataPtr = [&]() {
memcpy(frame.header, &oldmsg.ArbIDOrHeader, sizeof(frame.header));
if ((oldmsg.ExtraDataPtr != nullptr) && (oldmsg.ExtraDataPtrEnabled == 1))
frame.data = reinterpret_cast<const uint8_t *>(oldmsg.ExtraDataPtr);
else
frame.data = oldmsg.Data;
};
switch(oldmsg.Protocol)
{
case SPY_PROTOCOL_ETHERNET:
{
frame.length = ((oldmsg.NumberBytesHeader & 255) << 8) | (oldmsg.NumberBytesData & 255);
copyFrameDataPtr();
break;
}
case SPY_PROTOCOL_LIN:
{
neomessage_lin_t& linFrame = *reinterpret_cast<neomessage_lin_t*>(&frame);
const uint8_t numberBytesHeader = std::min(oldmsg.NumberBytesHeader, static_cast<uint8_t>(3));
const uint8_t numberBytesData = std::min(oldmsg.NumberBytesData, static_cast<uint8_t>(7));
frame.length = numberBytesHeader + numberBytesData;
linFrame.type = ICSNEO_NETWORK_TYPE_LIN;
if (oldmsg.StatusBitField & SPY_STATUS_INIT_MESSAGE)
linFrame.linStatus.txCommander = true;
else
linFrame.linStatus.txResponder = true;
copyFrameDataPtr();
if (frame.length > 2) {
size_t checksum = 0;
uint8_t* lastByte = nullptr;
for(size_t idx = 1; idx < (frame.length - 1); ++idx) {
if (idx < oldmsg.NumberBytesHeader) {
checksum += frame.header[idx];
lastByte = (frame.header + idx + 1);
} else {
checksum += frame.data[idx-numberBytesHeader];
lastByte = const_cast<uint8_t*>(frame.data) + idx - numberBytesHeader + 1;
}
if (checksum > 255) { checksum -= 255; }
}
size_t enhanced = frame.header[0] + checksum;
if (enhanced > 255) { enhanced -= 255; }
checksum ^= 0xff;
enhanced ^= 0xff;
if ((lastByte != nullptr) && (*lastByte != checksum) && (*lastByte == enhanced))
linFrame.linStatus.txChecksumEnhanced = true;
}
break;
}
case SPY_PROTOCOL_CANFD:
{
frame.status.canfdFDF = true;
copyFrameDataPtr();
break;
}
default:
{
frame.length = oldmsg.NumberBytesData;
copyFrameDataPtr();
break;
}
}
return true;
}
static inline bool Within(size_t value, size_t min, size_t max) static inline bool Within(size_t value, size_t min, size_t max)
{ {
return ((min <= value) && (value < max)); return ((min <= value) && (value < max));
@ -396,25 +507,9 @@ int LegacyDLLExport icsneoTxMessagesEx(void* hObject, icsSpyMessage* pMsg, unsig
*NumTxed = 0; *NumTxed = 0;
for (unsigned int i = 0; i < lNumMessages; i++) for (unsigned int i = 0; i < lNumMessages; i++)
{ {
const icsSpyMessage& oldmsg = pMsg[i];
newmsg = {}; newmsg = {};
newmsg.netid = (uint16_t)lNetworkID; const icsSpyMessage& oldMsg = pMsg[i];
newmsg.description = oldmsg.DescriptionID; SpyMessageToNeoMessage(oldMsg, newmsg, lNetworkID);
memcpy(newmsg.header, &oldmsg.ArbIDOrHeader, sizeof(newmsg.header));
if (oldmsg.Protocol != SPY_PROTOCOL_ETHERNET)
newmsg.length = oldmsg.NumberBytesData;
else
newmsg.length = ((oldmsg.NumberBytesHeader & 255) << 8) | (oldmsg.NumberBytesData & 255);
if (oldmsg.ExtraDataPtr != nullptr && oldmsg.ExtraDataPtrEnabled == 1)
newmsg.data = reinterpret_cast<const uint8_t *>(oldmsg.ExtraDataPtr);
else
newmsg.data = oldmsg.Data;
newmsg.status.statusBitfield[0] = oldmsg.StatusBitField;
newmsg.status.statusBitfield[1] = oldmsg.StatusBitField2;
newmsg.status.statusBitfield[2] = oldmsg.StatusBitField3;
newmsg.status.statusBitfield[3] = oldmsg.StatusBitField4;
if (oldmsg.Protocol == SPY_PROTOCOL_CANFD)
newmsg.status.canfdFDF = true;
if (icsneo_transmit(device, reinterpret_cast<neomessage_t*>(&newmsg))) if (icsneo_transmit(device, reinterpret_cast<neomessage_t*>(&newmsg)))
(*NumTxed)++; (*NumTxed)++;
} }

View File

@ -19,4 +19,12 @@ void LINMessage::calcChecksum(LINMessage& message) {
message.checksum ^= 0xFFu; message.checksum ^= 0xFFu;
} }
uint8_t LINMessage::calcProtectedID(uint8_t& id) {
uint8_t protID = id;
auto bit = [&](uint8_t pos)->uint8_t { return ((protID >> pos) & 0x1u); };
protID |= (~(bit(1) ^ bit(3) ^ bit(4) ^ bit(5)) << 7);
protID |= ((bit(0) ^ bit(1) ^ bit(2) ^ bit(4)) << 6);
return protID;
}
} //namespace icsneo } //namespace icsneo

View File

@ -2,6 +2,7 @@
#include "icsneo/communication/message/canmessage.h" #include "icsneo/communication/message/canmessage.h"
#include "icsneo/communication/message/ethernetmessage.h" #include "icsneo/communication/message/ethernetmessage.h"
#include "icsneo/communication/message/canerrorcountmessage.h" #include "icsneo/communication/message/canerrorcountmessage.h"
#include "icsneo/communication/message/linmessage.h"
using namespace icsneo; using namespace icsneo;
@ -17,6 +18,7 @@ neomessage_t icsneo::CreateNeoMessage(const std::shared_ptr<Message> message) {
neomessage_frame_t& frame = *(neomessage_frame_t*)&neomsg; neomessage_frame_t& frame = *(neomessage_frame_t*)&neomsg;
auto framemsg = std::static_pointer_cast<Frame>(message); auto framemsg = std::static_pointer_cast<Frame>(message);
const auto netType = framemsg->network.getType(); const auto netType = framemsg->network.getType();
frame.netid = (neonetid_t)framemsg->network.getNetID(); frame.netid = (neonetid_t)framemsg->network.getNetID();
frame.type = (neonettype_t)netType; frame.type = (neonettype_t)netType;
frame.description = framemsg->description; frame.description = framemsg->description;
@ -53,6 +55,47 @@ neomessage_t icsneo::CreateNeoMessage(const std::shared_ptr<Message> message) {
//eth.status.xyz = ethmsg->noPadding; //eth.status.xyz = ethmsg->noPadding;
break; break;
} }
case Network::Type::LIN: {
neomessage_lin_t& lin = *(neomessage_lin_t*)&neomsg;
auto linmsg = std::static_pointer_cast<LINMessage>(message);
if(!linmsg) { break; }
const auto linHdrBytes = std::min(linmsg->data.size(), static_cast<size_t>(2));
lin.header[0] = linmsg->protectedID;
std::copy(linmsg->data.begin(), linmsg->data.begin() + linHdrBytes, lin.header + 1);
linmsg->calcChecksum(*linmsg);
lin.checksum = linmsg->checksum;
lin.data = linmsg->data.data() + linHdrBytes;
if(linmsg->isEnhancedChecksum != linmsg->statusFlags.TxChecksumEnhanced) {
linmsg->isEnhancedChecksum = true;
linmsg->statusFlags.TxChecksumEnhanced = true;
}
if(linmsg->data.size())
lin.length = linmsg->data.size() + 2;
else
lin.length = 1;
lin.linStatus = {
linmsg->statusFlags.TxChecksumEnhanced,
linmsg->statusFlags.TxCommander,
linmsg->statusFlags.TxResponder,
linmsg->statusFlags.UpdateResponderOnce,
linmsg->statusFlags.HasUpdatedResponderOnce,
linmsg->statusFlags.BusRecovered,
linmsg->statusFlags.BreakOnly
};
lin.status.linJustBreakSync = linmsg->errFlags.ErrRxBreakSyncOnly;
lin.status.linErrorTXRXMismatch = linmsg->errFlags.ErrTxRxMismatch;
lin.status.linErrorRXBreakNotZero = linmsg->errFlags.ErrRxBreakNotZero;
lin.status.linErrorRXBreakTooShort = linmsg->errFlags.ErrRxBreakTooShort;
lin.status.linErrorRXSyncNot55 = linmsg->errFlags.ErrRxSyncNot55;
lin.status.linErrorRXDataGreaterEight = linmsg->errFlags.ErrRxDataLenOver8;
lin.status.linSyncFrameError = linmsg->errFlags.ErrFrameSync;
lin.status.linIDFrameError = linmsg->errFlags.ErrFrameMessageID;
lin.status.linSlaveByteError = linmsg->errFlags.ErrFrameResponderData;
lin.status.checksumError = linmsg->errFlags.ErrChecksumMatch;
break;
}
default: default:
// TODO Implement others // TODO Implement others
break; break;
@ -105,6 +148,53 @@ std::shared_ptr<Message> icsneo::CreateMessageFromNeoMessage(const neomessage_t*
ethmsg->data.insert(ethmsg->data.end(), eth.data, eth.data + eth.length); ethmsg->data.insert(ethmsg->data.end(), eth.data, eth.data + eth.length);
return ethmsg; return ethmsg;
} }
case Network::Type::LIN: {
neomessage_lin_t& lin = *(neomessage_lin_t*)neomessage;
auto linmsg = std::make_shared<LINMessage>();
linmsg->network = network;
linmsg->description = lin.description;
linmsg->protectedID = lin.header[0];
linmsg->ID = linmsg->protectedID & 0x3F;
linmsg->statusFlags = {
static_cast<bool>(lin.linStatus.txChecksumEnhanced),
static_cast<bool>(lin.linStatus.txCommander),
static_cast<bool>(lin.linStatus.txResponder),
static_cast<bool>(lin.linStatus.updateResponderOnce),
static_cast<bool>(lin.linStatus.hasUpdatedResponderOnce),
static_cast<bool>(lin.linStatus.busRecovered),
static_cast<bool>(lin.linStatus.breakOnly)
};
linmsg->isEnhancedChecksum = linmsg->statusFlags.TxChecksumEnhanced;
linmsg->errFlags = {
static_cast<bool>(lin.linStatus.breakOnly),
static_cast<bool>(lin.status.linJustBreakSync),
static_cast<bool>(lin.status.linErrorTXRXMismatch),
static_cast<bool>(lin.status.linErrorRXBreakNotZero),
static_cast<bool>(lin.status.linErrorRXBreakTooShort),
static_cast<bool>(lin.status.linErrorRXSyncNot55),
static_cast<bool>(lin.status.linErrorRXDataGreaterEight),
static_cast<bool>(lin.status.linSyncFrameError),
static_cast<bool>(lin.status.linIDFrameError),
static_cast<bool>(lin.status.linSlaveByteError),
static_cast<bool>(lin.status.checksumError)
};
if(lin.length > 1) {
auto numHeaderBytes = std::min(lin.length, static_cast<size_t>(3));
linmsg->data.insert(linmsg->data.end(), (lin.header + 1), (lin.header + numHeaderBytes));
linmsg->data.insert(linmsg->data.end(), lin.data, (lin.data + (lin.length - numHeaderBytes)));
linmsg->checksum = linmsg->data.back();
linmsg->data.pop_back();
}
if (linmsg->statusFlags.TxCommander) {
if (linmsg->data.size())
linmsg->linMsgType = icsneo::LINMessage::Type::LIN_COMMANDER_MSG;
else
linmsg->linMsgType = icsneo::LINMessage::Type::LIN_HEADER_ONLY;
} else if (linmsg->statusFlags.TxResponder) {
linmsg->linMsgType = icsneo::LINMessage::Type::LIN_UPDATE_RESPONDER;
}
return linmsg;
}
default: break; default: break;
} }
break; break;

View File

@ -5,7 +5,6 @@
namespace icsneo { namespace icsneo {
std::shared_ptr<Message> HardwareLINPacket::DecodeToMessage(const std::vector<uint8_t>& bytestream) { std::shared_ptr<Message> HardwareLINPacket::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
auto msg = std::make_shared<LINMessage>();
const HardwareLINPacket* packet = reinterpret_cast<const HardwareLINPacket*>(bytestream.data()); const HardwareLINPacket* packet = reinterpret_cast<const HardwareLINPacket*>(bytestream.data());
size_t numDataBytes = packet->CoreMiniBitsLIN.len; size_t numDataBytes = packet->CoreMiniBitsLIN.len;
size_t numHeaderBytes = sizeof(HardwareLINPacket::CoreMiniBitsLIN); size_t numHeaderBytes = sizeof(HardwareLINPacket::CoreMiniBitsLIN);
@ -17,14 +16,13 @@ std::shared_ptr<Message> HardwareLINPacket::DecodeToMessage(const std::vector<ui
if(numDataBytes) if(numDataBytes)
--numDataBytes; //If data is present, there will be a checksum included --numDataBytes; //If data is present, there will be a checksum included
auto msg = std::make_shared<LINMessage>(static_cast<uint8_t>(packet->CoreMiniBitsLIN.ID));
msg->network = Network::GetNetIDFromCoreMiniNetwork(static_cast<Network::CoreMini>(packet->networkID)); msg->network = Network::GetNetIDFromCoreMiniNetwork(static_cast<Network::CoreMini>(packet->networkID));
msg->protectedID = packet->CoreMiniBitsLIN.ID;
msg->ID = (packet->CoreMiniBitsLIN.ID & 0x3Fu);
msg->isEnhancedChecksum = static_cast<bool>(packet->CoreMiniBitsLIN.TxChkSumEnhanced); msg->isEnhancedChecksum = static_cast<bool>(packet->CoreMiniBitsLIN.TxChkSumEnhanced);
/* Minimum one responder byte and one checksum byte. */ /* Minimum one responder byte and one checksum byte. */
if(2u > packet->CoreMiniBitsLIN.len) if(2u > packet->CoreMiniBitsLIN.len)
msg->type = LINMessage::Type::LIN_ERROR; msg->linMsgType = LINMessage::Type::LIN_ERROR;
auto dataStart = bytestream.begin() + numHeaderBytes; auto dataStart = bytestream.begin() + numHeaderBytes;
std::copy(dataStart, (dataStart+numDataBytes), std::back_inserter(msg->data)); std::copy(dataStart, (dataStart+numDataBytes), std::back_inserter(msg->data));
@ -78,16 +76,16 @@ std::shared_ptr<Message> HardwareLINPacket::DecodeToMessage(const std::vector<ui
static_cast<bool>(packet->CoreMiniBitsLIN.BreakOnly) static_cast<bool>(packet->CoreMiniBitsLIN.BreakOnly)
}; };
if(msg->statusFlags.TxCommander || msg->statusFlags.TxResponder) if(msg->statusFlags.TxCommander || msg->statusFlags.TxResponder)
msg->type = LINMessage::Type::LIN_COMMANDER_MSG; msg->linMsgType = LINMessage::Type::LIN_COMMANDER_MSG;
else if(msg->statusFlags.BreakOnly) else if(msg->statusFlags.BreakOnly)
msg->type = LINMessage::Type::LIN_BREAK_ONLY; msg->linMsgType = LINMessage::Type::LIN_BREAK_ONLY;
if( msg->errFlags.ErrRxBreakOnly || msg->errFlags.ErrRxBreakSyncOnly || if( msg->errFlags.ErrRxBreakOnly || msg->errFlags.ErrRxBreakSyncOnly ||
msg->errFlags.ErrTxRxMismatch || msg->errFlags.ErrRxBreakNotZero || msg->errFlags.ErrTxRxMismatch || msg->errFlags.ErrRxBreakNotZero ||
msg->errFlags.ErrRxBreakTooShort || msg->errFlags.ErrRxSyncNot55 || msg->errFlags.ErrRxBreakTooShort || msg->errFlags.ErrRxSyncNot55 ||
msg->errFlags.ErrRxDataLenOver8 || msg->errFlags.ErrFrameSync || msg->errFlags.ErrRxDataLenOver8 || msg->errFlags.ErrFrameSync ||
msg->errFlags.ErrFrameMessageID || msg->errFlags.ErrChecksumMatch || msg->errFlags.ErrFrameMessageID || msg->errFlags.ErrChecksumMatch ||
msg->errFlags.ErrFrameResponderData ) msg->errFlags.ErrFrameResponderData )
{ msg->type = LINMessage::Type::LIN_ERROR; } { msg->linMsgType = LINMessage::Type::LIN_ERROR; }
msg->timestamp = packet->timestamp; msg->timestamp = packet->timestamp;
return msg; return msg;
@ -97,7 +95,7 @@ bool HardwareLINPacket::EncodeFromMessage(LINMessage& message, std::vector<uint8
{ {
uint8_t size = ((std::min<size_t>(8ul, message.data.size()) + 3ul) & 0xFu); uint8_t size = ((std::min<size_t>(8ul, message.data.size()) + 3ul) & 0xFu);
if(size > 3) { ++size; } // add a checksum byte if there's data if(size > 3) { ++size; } // add a checksum byte if there's data
switch(message.type) { switch(message.linMsgType) {
case LINMessage::Type::LIN_HEADER_ONLY: case LINMessage::Type::LIN_HEADER_ONLY:
case LINMessage::Type::LIN_COMMANDER_MSG: case LINMessage::Type::LIN_COMMANDER_MSG:
{ {
@ -117,12 +115,7 @@ bool HardwareLINPacket::EncodeFromMessage(LINMessage& message, std::vector<uint8
default: default:
break; break;
} }
message.calcProtectedID(message.ID);
message.protectedID = message.ID;
auto bit = [&](uint8_t pos)->uint8_t { return ((message.protectedID >> pos) & 0x1u); };
message.protectedID |= (~(bit(1) ^ bit(3) ^ bit(4) ^ bit(5)) << 7);
message.protectedID |= ((bit(0) ^ bit(1) ^ bit(2) ^ bit(4)) << 6);
bytestream.insert(bytestream.end(), bytestream.insert(bytestream.end(),
{ {
static_cast<uint8_t>(0x00u), static_cast<uint8_t>(0x00u),
@ -132,7 +125,7 @@ bool HardwareLINPacket::EncodeFromMessage(LINMessage& message, std::vector<uint8
static_cast<uint8_t>(message.protectedID) static_cast<uint8_t>(message.protectedID)
}); });
switch(message.type) { switch(message.linMsgType) {
case(LINMessage::Type::LIN_COMMANDER_MSG): case(LINMessage::Type::LIN_COMMANDER_MSG):
case(LINMessage::Type::LIN_UPDATE_RESPONDER): case(LINMessage::Type::LIN_UPDATE_RESPONDER):
{ {
@ -144,6 +137,7 @@ bool HardwareLINPacket::EncodeFromMessage(LINMessage& message, std::vector<uint8
default: default:
break; break;
} }
if(bytestream.size() % 2) if(bytestream.size() % 2)
bytestream.push_back(0x41); //padding bytestream.push_back(0x41); //padding

View File

@ -1,4 +1,6 @@
option(LIBICSNEO_BUILD_C_INTERACTIVE_EXAMPLE "Build the command-line interactive C example." ON) option(LIBICSNEO_BUILD_C_INTERACTIVE_EXAMPLE "Build the command-line interactive C example." ON)
option(LIBICSNEO_BUILD_C_SIMPLE_EXAMPLE "Build the command-line simple C example." ON)
option(LIBICSNEO_BUILD_C_LEGACY_EXAMPLE "Build the command-line simple C example." ON)
option(LIBICSNEO_BUILD_CPP_SIMPLE_EXAMPLE "Build the simple C++ example." ON) option(LIBICSNEO_BUILD_CPP_SIMPLE_EXAMPLE "Build the simple C++ example." ON)
option(LIBICSNEO_BUILD_CPP_INTERACTIVE_EXAMPLE "Build the command-line interactive C++ example." ON) option(LIBICSNEO_BUILD_CPP_INTERACTIVE_EXAMPLE "Build the command-line interactive C++ example." ON)
option(LIBICSNEO_BUILD_CPP_A2B_EXAMPLE "Build the A2B example." ON) option(LIBICSNEO_BUILD_CPP_A2B_EXAMPLE "Build the A2B example." ON)
@ -11,6 +13,14 @@ if(LIBICSNEO_BUILD_C_INTERACTIVE_EXAMPLE)
add_subdirectory(c/interactive) add_subdirectory(c/interactive)
endif() endif()
if(LIBICSNEO_BUILD_C_SIMPLE_EXAMPLE)
add_subdirectory(c/simple)
endif()
if(LIBICSNEO_BUILD_C_LEGACY_EXAMPLE)
add_subdirectory(c/legacy)
endif()
if(LIBICSNEO_BUILD_CPP_SIMPLE_EXAMPLE) if(LIBICSNEO_BUILD_CPP_SIMPLE_EXAMPLE)
add_subdirectory(cpp/simple) add_subdirectory(cpp/simple)
endif() endif()

View File

@ -14,3 +14,4 @@ add_executable(libicsneoc-interactive-example src/main.c)
if(UNIX) if(UNIX)
target_link_libraries(libicsneoc-interactive-example ${CMAKE_DL_LIBS}) target_link_libraries(libicsneoc-interactive-example ${CMAKE_DL_LIBS})
endif() endif()
target_link_libraries(libicsneoc-interactive-example icsneoc)

View File

@ -1,5 +1,5 @@
// Signal to dynamically load the library // Signal to dynamically load the library
#define ICSNEOC_DYNAMICLOAD //#define ICSNEOC_DYNAMICLOAD
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -219,21 +219,21 @@ int main() {
// Attempt to initialize the library and access its functions // Attempt to initialize the library and access its functions
// This call searches for icsneoc.dll according to the standard dynamic-link library search order // This call searches for icsneoc.dll according to the standard dynamic-link library search order
int ret = icsneo_init(); //int ret = icsneo_init();
if(ret == 1) { //if(ret == 1) {
printf("The library was already initialized!\n"); // printf("The library was already initialized!\n");
return ret; // return ret;
} //}
//
if(ret == 2) { //if(ret == 2) {
printf("The library could not be found!\n"); // printf("The library could not be found!\n");
return ret; // return ret;
} //}
//
if(ret == 3) { //if(ret == 3) {
printf("The library is missing functions!\n"); // printf("The library is missing functions!\n");
return ret; // return ret;
} //}
neoversion_t ver = icsneo_getVersion(); neoversion_t ver = icsneo_getVersion();
printf("ICS icsneoc.dll version %u.%u.%u\n\n", ver.major, ver.minor, ver.patch); printf("ICS icsneoc.dll version %u.%u.%u\n\n", ver.major, ver.minor, ver.patch);
@ -487,6 +487,31 @@ int main() {
printf("(%"PRIu64")\n", canMsg->timestamp); printf("(%"PRIu64")\n", canMsg->timestamp);
break; break;
} }
case ICSNEO_NETWORK_TYPE_LIN: {
neomessage_lin_t* linMsg = (neomessage_lin_t*)frame;
size_t frameLen = linMsg->length;
size_t dataLen = (frameLen > 2) ? (frameLen - 2) : 0;
size_t numberBytesHeader = (dataLen > 1) ? 3 : 1;
size_t numberBytesData = frameLen - numberBytesHeader;
if(linMsg->netid == ICSNEO_NETID_LIN) {
printf("LIN 1 | ID: 0x%02x [%zu] ", linMsg->header[0], dataLen);
}
else if (linMsg->netid == ICSNEO_NETID_LIN2) {
printf("LIN 2 | ID: 0x%02x [%zu] ", linMsg->header[0], dataLen);
}
for(size_t i = 0; i < dataLen; ++i) {
if (i < 2) {
printf("%02x ", linMsg->header[i+1]);
} else {
printf("%02x ", linMsg->data[i-2]);
}
}
if(numberBytesData > 0)
printf("| Checksum: 0x%02x\n", linMsg->data[numberBytesData-1]);
else
printf("| Checksum: 0x%02x\n", linMsg->header[numberBytesHeader-1]);
}
default: default:
printf("\tMessage on netid %d with length %zu\n", frame->netid, frame->length); printf("\tMessage on netid %d with length %zu\n", frame->netid, frame->length);
break; break;
@ -762,7 +787,7 @@ int main() {
case 'X': case 'X':
case 'x': case 'x':
printf("Exiting program\n"); printf("Exiting program\n");
return !icsneo_close(); return 0;
default: default:
printf("Unexpected input, exiting!\n"); printf("Unexpected input, exiting!\n");
return 1; return 1;

View File

@ -0,0 +1,5 @@
cmake_minimum_required(VERSION 3.2)
project(libicsneoc-legacy-lin-example VERSION 0.2.0)
add_executable(libicsneoc-legacy-lin-example lin/main.c)
target_link_libraries(libicsneoc-legacy-lin-example icsneolegacy)

View File

@ -0,0 +1,80 @@
# libicsneo C Example
This is an example console application that uses the icsneoc library to control an Intrepid Control Systems hardware device.
## Cloning
This will create a copy of the repository on your local machine.
Run:
```shell
git clone https://github.com/intrepidcs/libicsneo-examples -b v0.2.0-dev --recursive
```
Alternatively, if you cloned without the `--recursive` flag, you must enter the `libicsneo-examples` folder and run the following:
```shell
git submodule update --recursive --init
```
If you haven't done this, `third-party/libicsneo` will be empty and you won't be able to build!
## Windows using Visual Studio 2017+
### Building the DLL
First, we are going to build the icsneoc library into a .dll file that we can later use in order to access the library functions.
1. Launch Visual Studio and open the `libicsneo-examples` folder.
2. Choose `File->Open->Cmake...`
3. Navigate to `third-party/libicsneo` and select the `CMakeLists.txt` there.
4. Visual Studio will process the CMake project.
5. Select `Build->Rebuild All`
6. Visual Studio will generate the `icsneoc.dll` file, which can then be found by selecting `Project->Cmake Cache (x64-Debug Only)->Open in Explorer`. If the file cannot be found, search in `libicsneo-examples/third-party/libicsneo/out/build/x64-Debug` and double-check that the build succeeded in step 5.
7. Move the `icsneoc.dll` file to the `/C/Windows/System32` folder. This will allow it to be found by icsneo_init(), which loads all the library functions.
* Alternatively, the `icsneoc.dll` file can be placed in the same directory as `libicsneoc-example.exe`, which is typically `libicsneo-examples/libicsneoc-example/out/build/x64-Debug`, although this is not recommended. For more information, refer to [the Microsoft documentation](https://docs.microsoft.com/en-us/windows/desktop/dlls/dynamic-link-library-search-order).
### Building the example program
Although the example program will build without successfully completing the steps above, it will exit immediately upon running due to a failure to load any library functions.
1. Choose `File->Open->Cmake...`
2. Navigate to `libicsneo-examples/libicsneoc-example` and select the `CMakeLists.txt` there.
3. Visual Studio will process the CMake project.
4. Select `Build->Rebuild All`
5. Click on the dropdown arrow attached to the green play button (labelled "Select Startup Item") and select `libicsneoc-example.exe`
6. Click on the green play button to run the example.
## Ubuntu 18.04 LTS
### Building the .so
First, we are going to build the icsneoc library into a .so file that we can later use in order to access the library functions.
1. Install dependencies with `sudo apt update` then `sudo apt install build-essential cmake libusb-1.0-0-dev libpcap0.8-dev`
2. Change directories to `libicsneo-examples/third-party/libicsneo` and create a build directory by running `mkdir -p build`
3. Enter the build directory with `cd build`
4. Run `cmake ..` to generate your Makefile.
* Hint! Running `cmake -DCMAKE_BUILD_TYPE=Debug ..` will generate the proper scripts to build debug, and `cmake -DCMAKE_BUILD_TYPE=Release ..` will generate the proper scripts to build with all optimizations on.
5. Run `make` to build the library.
* Hint! Speed up your build by using multiple processors! Use `make -j#` where `#` is the number of cores/threads your system has plus one. For instance, on a standard 8 thread Intel i7, you might use `-j9` for an ~8x speedup.
6. Run `sudo cp libicsneoc.so /usr/lib` so that it can be found via the default ubuntu .so search path. For more information, see the [ld.so.8 man page](http://man7.org/linux/man-pages/man8/ld.so.8.html).
### Building the example program
Although the example program will build without successfully completing the steps above, it will exit immediately upon running due to a failure to load any library functions.
1. Change directories to `libicsneo-examples/libicsneoc-example`
2. Create a build directory by running `mkdir -p build`
3. Enter the build directory with `cd build`
4. Run `cmake ..` to generate your Makefile.
* Hint! Running `cmake -DCMAKE_BUILD_TYPE=Debug ..` will generate the proper scripts to build debug, and `cmake -DCMAKE_BUILD_TYPE=Release ..` will generate the proper scripts to build with all optimizations on.
5. Run `make` to build the library.
* Hint! Speed up your build by using multiple processors! Use `make -j#` where `#` is the number of cores/threads your system has plus one. For instance, on a standard 8 thread Intel i7, you might use `-j9` for an ~8x speedup.
6. Run `sudo ./libicsneoc-example` to run the example.
* Hint! In order to run without sudo, you will need to set up the udev rules. Copy `libicsneo-examples/third-party/libicsneo/99-intrepidcs.rules` to `/etc/udev/rules.d`, then run `udevadm control --reload-rules && udevadm trigger` afterwards. While the program will still run without setting up these rules, it will fail to open any devices.
## macOS
Instructions coming soon&trade;

View File

@ -0,0 +1,165 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdbool.h>
#if defined _WIN32
#include "icsneo/platform/windows.h"
#define SLEEP(msecs) Sleep(msecs)
#elif defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
#include <time.h>
#define SLEEP(msecs) do { \
struct timespec ts; \
ts.tv_sec = msecs/1000; \
ts.tv_nsec = msecs%1000*1000; \
nanosleep(&ts, NULL); \
} while (0)
#else
#error "Platform unknown"
#endif
// Get the PRIu64 macro for timestamps
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
// Include icsneo/icsneolegacy.h to access library functions
#include "icsneo/icsneolegacy.h"
int main() {
int ver = icsneoGetDLLVersion();
printf("ICS icsneolegacy.dll version %u\n\n", ver);
// Find and attempt to open device
//legacy open device
int numDevices = 10;
NeoDevice devices[10];
void* hObject; // holds a handle to the neoVI object
int iRetVal = 0;
int deviceTypes = 0;
int iResult = 0;
iRetVal = icsneoFindNeoDevices(deviceTypes, devices, &numDevices);
if(iRetVal) {
// Attempt to open the selected device, enable message polling, and go online
iRetVal = icsneoOpenNeoDevice(&devices[0], &hObject, NULL, 1, 0);
if(iRetVal) {
printf("Device found and opened!\n");
} else {
printf("Device found but failed to open!\n");
}
} else {
printf("No new devices found!\n");
}
// Send message LIN
{
//lin responder frame
icsSpyMessageJ1850 msg1 = {0};
int lNetworkID;
msg1.Protocol = SPY_PROTOCOL_LIN;
msg1.StatusBitField = 0;
msg1.StatusBitField2 = 0;
lNetworkID = NETID_LIN2;
msg1.Header[0] = 0x11; //protected ID
msg1.Header[1] = 0xaa;
msg1.Header[2] = 0xbb;
msg1.Data[0] = 0xcc;
msg1.Data[1] = 0xdd;
msg1.Data[2] = 0x11;
msg1.Data[3] = 0x22;
msg1.Data[4] = 0x33;
msg1.Data[5] = 0x44;
msg1.Data[6] = 0x44; //checksum 0x33 enhanced
msg1.NumberBytesData = 7;
msg1.NumberBytesHeader = 3;
iRetVal = icsneoTxMessages(hObject, (icsSpyMessage*)&msg1, lNetworkID, 1);
if(!iRetVal)
printf("Device failed to transmit LIN responder update\n");
else
printf("Transmitted successfully!\n");
icsSpyMessageJ1850 msg2 = {0};
msg2.Protocol = SPY_PROTOCOL_LIN;
msg2.StatusBitField = SPY_STATUS_INIT_MESSAGE;
lNetworkID = NETID_LIN;
msg2.Header[0] = 0x11; //protected ID
msg2.NumberBytesData = 0;
msg2.NumberBytesHeader = 1;
iRetVal = icsneoTxMessages(hObject, (icsSpyMessage*)&msg2, lNetworkID, 1);
if(!iRetVal)
printf("Device failed to transmit LIN commander header\n");
else
printf("Transmitted successfully!\n");
SLEEP(250);
icsSpyMessageJ1850 msg3 = {0};
msg3.Protocol = SPY_PROTOCOL_LIN;
msg3.StatusBitField = SPY_STATUS_INIT_MESSAGE;
msg3.StatusBitField2 = 0;
lNetworkID = NETID_LIN;
msg3.Header[0] = 0xe2; //protected ID
msg3.Header[1] = 0x44;
msg3.Header[2] = 0x33;
msg3.Data[0] = 0x22;
msg3.Data[1] = 0x11;
msg3.Data[2] = 0x11;
msg3.Data[3] = 0x22;
msg3.Data[4] = 0x33;
msg3.Data[5] = 0x44;
msg3.Data[6] = 0xc7; //checksum
msg3.NumberBytesData = 7;
msg3.NumberBytesHeader = 3;
iRetVal = icsneoTxMessages(hObject, (icsSpyMessage*)&msg3, lNetworkID, 1);
if(!iRetVal)
printf("Device failed to transmit LIN commander message\n");
else
printf("Transmitted successfully!\n");
}
SLEEP(1000);
// Get messages
{
static icsSpyMessage rxMsg[30000];
int numMessages = 0;
int numErrors = 0;
iRetVal = icsneoGetMessages(hObject, rxMsg, &numMessages, &numErrors);
if(!iRetVal)
printf("Get Messages failed!\n");
else
for(int idx = 0; idx < numMessages; ++idx)
{
if(rxMsg[idx].Protocol == SPY_PROTOCOL_LIN) {
const icsSpyMessageJ1850* linMsg = (icsSpyMessageJ1850*)&rxMsg[idx];
size_t frameLen = (linMsg->NumberBytesHeader + linMsg->NumberBytesData);
size_t dataLen = (frameLen > 2) ? (frameLen - 2) : 0;
if(linMsg->NetworkID == NETID_LIN) {
printf("LIN 1 | ID: 0x%02x [%zu] ", linMsg->Header[0], dataLen);
}
else if (linMsg->NetworkID == NETID_LIN2) {
printf("LIN 2 | ID: 0x%02x [%zu] ", linMsg->Header[0], dataLen);
}
for(size_t i = 0; i < dataLen; ++i) {
if (i < 2) {
printf("%02x ", linMsg->Header[i+1]);
} else {
printf("%02x ", linMsg->Data[i-2]);
}
}
if(linMsg->NumberBytesData > 0)
printf("| Checksum: 0x%02x\n", linMsg->Data[linMsg->NumberBytesData-1]);
else
printf("| Checksum: 0x%02x\n", linMsg->Header[linMsg->NumberBytesHeader-1]);
}
}
}
int iNumberOfErrors = 0;
// Attempt to close the device
{
// Close Communication
iResult = icsneoClosePort(hObject, &iNumberOfErrors);
}
printf("Exiting program\n");
return iResult;
}

View File

@ -0,0 +1,17 @@
cmake_minimum_required(VERSION 3.2)
project(libicsneoc-simple-lin-example VERSION 0.2.0)
include(GNUInstallDirs)
# Include libicsneo's include directory
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../include)
if(UNIX)
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS)
endif()
add_executable(libicsneoc-simple-lin-example lin/main.c)
if(UNIX)
target_link_libraries(libicsneoc-simple-lin-example ${CMAKE_DL_LIBS})
endif()
target_link_libraries(libicsneoc-simple-lin-example icsneoc)

View File

@ -0,0 +1,80 @@
# libicsneo C Example
This is an example console application that uses the icsneoc library to control an Intrepid Control Systems hardware device.
## Cloning
This will create a copy of the repository on your local machine.
Run:
```shell
git clone https://github.com/intrepidcs/libicsneo-examples -b v0.2.0-dev --recursive
```
Alternatively, if you cloned without the `--recursive` flag, you must enter the `libicsneo-examples` folder and run the following:
```shell
git submodule update --recursive --init
```
If you haven't done this, `third-party/libicsneo` will be empty and you won't be able to build!
## Windows using Visual Studio 2017+
### Building the DLL
First, we are going to build the icsneoc library into a .dll file that we can later use in order to access the library functions.
1. Launch Visual Studio and open the `libicsneo-examples` folder.
2. Choose `File->Open->Cmake...`
3. Navigate to `third-party/libicsneo` and select the `CMakeLists.txt` there.
4. Visual Studio will process the CMake project.
5. Select `Build->Rebuild All`
6. Visual Studio will generate the `icsneoc.dll` file, which can then be found by selecting `Project->Cmake Cache (x64-Debug Only)->Open in Explorer`. If the file cannot be found, search in `libicsneo-examples/third-party/libicsneo/out/build/x64-Debug` and double-check that the build succeeded in step 5.
7. Move the `icsneoc.dll` file to the `/C/Windows/System32` folder. This will allow it to be found by icsneo_init(), which loads all the library functions.
* Alternatively, the `icsneoc.dll` file can be placed in the same directory as `libicsneoc-example.exe`, which is typically `libicsneo-examples/libicsneoc-example/out/build/x64-Debug`, although this is not recommended. For more information, refer to [the Microsoft documentation](https://docs.microsoft.com/en-us/windows/desktop/dlls/dynamic-link-library-search-order).
### Building the example program
Although the example program will build without successfully completing the steps above, it will exit immediately upon running due to a failure to load any library functions.
1. Choose `File->Open->Cmake...`
2. Navigate to `libicsneo-examples/libicsneoc-example` and select the `CMakeLists.txt` there.
3. Visual Studio will process the CMake project.
4. Select `Build->Rebuild All`
5. Click on the dropdown arrow attached to the green play button (labelled "Select Startup Item") and select `libicsneoc-example.exe`
6. Click on the green play button to run the example.
## Ubuntu 18.04 LTS
### Building the .so
First, we are going to build the icsneoc library into a .so file that we can later use in order to access the library functions.
1. Install dependencies with `sudo apt update` then `sudo apt install build-essential cmake libusb-1.0-0-dev libpcap0.8-dev`
2. Change directories to `libicsneo-examples/third-party/libicsneo` and create a build directory by running `mkdir -p build`
3. Enter the build directory with `cd build`
4. Run `cmake ..` to generate your Makefile.
* Hint! Running `cmake -DCMAKE_BUILD_TYPE=Debug ..` will generate the proper scripts to build debug, and `cmake -DCMAKE_BUILD_TYPE=Release ..` will generate the proper scripts to build with all optimizations on.
5. Run `make` to build the library.
* Hint! Speed up your build by using multiple processors! Use `make -j#` where `#` is the number of cores/threads your system has plus one. For instance, on a standard 8 thread Intel i7, you might use `-j9` for an ~8x speedup.
6. Run `sudo cp libicsneoc.so /usr/lib` so that it can be found via the default ubuntu .so search path. For more information, see the [ld.so.8 man page](http://man7.org/linux/man-pages/man8/ld.so.8.html).
### Building the example program
Although the example program will build without successfully completing the steps above, it will exit immediately upon running due to a failure to load any library functions.
1. Change directories to `libicsneo-examples/libicsneoc-example`
2. Create a build directory by running `mkdir -p build`
3. Enter the build directory with `cd build`
4. Run `cmake ..` to generate your Makefile.
* Hint! Running `cmake -DCMAKE_BUILD_TYPE=Debug ..` will generate the proper scripts to build debug, and `cmake -DCMAKE_BUILD_TYPE=Release ..` will generate the proper scripts to build with all optimizations on.
5. Run `make` to build the library.
* Hint! Speed up your build by using multiple processors! Use `make -j#` where `#` is the number of cores/threads your system has plus one. For instance, on a standard 8 thread Intel i7, you might use `-j9` for an ~8x speedup.
6. Run `sudo ./libicsneoc-example` to run the example.
* Hint! In order to run without sudo, you will need to set up the udev rules. Copy `libicsneo-examples/third-party/libicsneo/99-intrepidcs.rules` to `/etc/udev/rules.d`, then run `udevadm control --reload-rules && udevadm trigger` afterwards. While the program will still run without setting up these rules, it will fail to open any devices.
## macOS
Instructions coming soon&trade;

View File

@ -0,0 +1,427 @@
// Signal to dynamically load the library
//#define ICSNEOC_DYNAMICLOAD
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
// Get the PRIu64 macro for timestamps
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
// Include icsneo/icsneoc.h to access library functions
#include "icsneo/icsneoc.h"
#ifdef _WIN32
#define SLEEP(msecs) Sleep(msecs)
#elif defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
#include <time.h>
#define SLEEP(msecs) do { \
struct timespec ts; \
ts.tv_sec = msecs/1000; \
ts.tv_nsec = msecs%1000*1000; \
nanosleep(&ts, NULL); \
} while (0)
#else
#error "Platform unknown"
#endif
size_t msgLimit = 50000;
size_t numDevices = 0;
neodevice_t devices[99];
const neodevice_t* selectedDevice = NULL;
/**
* \brief Prints all current known devices to output in the following format:
* [num] DeviceType SerialNum Connected: Yes/No Online: Yes/No Msg Polling: On/Off
*
* If any devices could not be described due to an error, they will appear in the following format:
* Description for device num not available!
*/
void printAllDevices() {
if(numDevices == 0) {
printf("No devices found! Please scan for new devices.\n");
}
for(size_t i = 0; i < numDevices; i++) {
char productDescription[ICSNEO_DEVICETYPE_LONGEST_DESCRIPTION] = { 0 };
size_t descriptionLength = ICSNEO_DEVICETYPE_LONGEST_DESCRIPTION;
// Updates productDescription and descriptionLength for each device
if(icsneo_describeDevice(devices + i, productDescription, &descriptionLength)) {
printf("[%zd] %s\tConnected: ", i + 1, productDescription);
if(icsneo_isOpen(devices + i)) {
printf("Yes\t");
} else printf("No\t");
printf("Online: ");
if(icsneo_isOnline(devices + i)) {
printf("Yes\t");
} else printf("No\t");
printf("Msg Polling: ");
if(icsneo_isMessagePollingEnabled(devices + i)) {
printf("On\n");
} else printf("Off\n");
} else {
printf("Description for device %zd not available!\n", i + 1);
}
}
}
/**
* \brief Scans for any new devices, adding them to devices and updating numDevices accordingly
* A total of 99 devices may be stored at once
*/
size_t scanNewDevices() {
neodevice_t newDevices[99];
size_t numNewDevices = 99;
icsneo_findAllDevices(newDevices, &numNewDevices);
for(size_t i = 0; i < numNewDevices; ++i) {
devices[numDevices + i] = newDevices[i];
}
numDevices += numNewDevices;
return numNewDevices;
}
void printLastError() {
neoevent_t error;
if(icsneo_getLastError(&error))
printf("Error 0x%u: %s\n", error.eventNumber, error.description);
else
printf("No errors found!\n");
}
/**
* \brief Gets all current API events and prints them to output
* Flushes the API event cache, meaning future calls (barring any new events) will not detect any further API events
*/
void printAPIEvents() {
neoevent_t events[99];
size_t eventCount = 99;
if(icsneo_getEvents(events, &eventCount)) {
if(eventCount == 1) {
printf("1 API event found!\n");
printf("Event 0x%u: %s\n", events[0].eventNumber, events[0].description);
} else {
printf("%d API events found!\n", (int) eventCount);
for(size_t i = 0; i < eventCount; ++i) {
printf("Event 0x%u: %s\n", events[i].eventNumber, events[i].description);
}
}
} else {
printf("Failed to get API events!\n");
}
}
/**
* \brief Gets all current device events and prints them to output. If no device events were found, printAPIEvents() is called
* Flushes the device event cache, meaning future calls (barring any new events) will not detect any further device events for this device
*/
void printDeviceEvents(neodevice_t* device) {
neoevent_t events[99];
size_t eventCount = 99;
if(icsneo_getDeviceEvents(selectedDevice, events, &eventCount)) {
if(eventCount == 1) {
printf("1 device event found!\n");
printf("Event 0x%x: %s\n", events[0].eventNumber, events[0].description);
} else {
printf("%d device events found!\n", (int) eventCount);
for(size_t i = 0; i < eventCount; ++i) {
printf("Event 0x%x: %s\n", events[i].eventNumber, events[i].description);
}
}
}
}
/**
* \brief Used to check character inputs for correctness (if they are found in an expected list)
* \param[in] numArgs the number of possible options for the expected character
* \param[in] ... the possible options for the expected character
* \returns the entered character
*
* This function repeatedly prompts the user for input until a matching input is entered
* Example usage: char input = getCharInput(5, 'F', 'u', 'b', 'a', 'r');
*/
char getCharInput(int numArgs, ...) {
// 99 chars shold be more than enough to catch any typos
char input[99];
bool found = false;
va_list vaList;
va_start(vaList, numArgs);
char* list = (char*) calloc(numArgs, sizeof(char));
for(int i = 0; i < numArgs; ++i) {
*(list + i) = va_arg(vaList, int);
}
va_end(vaList);
while(!found) {
fgets(input, 99, stdin);
if(strlen(input) == 2) {
for(int i = 0; i < numArgs; ++i) {
if(input[0] == *(list + i)) {
found = true;
break;
}
}
}
if(!found) {
printf("Input did not match expected options. Please try again.\n");
}
}
free(list);
return input[0];
}
/**
* \brief Prompts the user to select a device from the list of currently known devices
* \returns a pointer to the device in devices[] selected by the user
* Requires an input from 1-9, so a maximum of 9 devices are supported
*/
const neodevice_t* selectDevice() {
printf("Please select a device:\n");
printAllDevices();
printf("\n");
size_t selectedDeviceNum = 10;
while(selectedDeviceNum > numDevices) {
char deviceSelection = getCharInput(9, '1', '2', '3', '4', '5', '6', '7', '8', '9');
if(deviceSelection < '0') {
printf("Selected device out of range!\n");
continue;
}
selectedDeviceNum = deviceSelection - '0';
if(selectedDeviceNum > numDevices) {
printf("Selected device out of range!\n");
}
}
printf("\n");
return devices + selectedDeviceNum - 1;
}
int main() {
neoversion_t ver = icsneo_getVersion();
printf("ICS icsneoc version %u.%u.%u\n\n", ver.major, ver.minor, ver.patch);
// Find and attempt to open device
size_t numNewDevices = scanNewDevices();
if(numNewDevices == 1) {
printf("1 new device found!\n");
} else {
printf("%d new devices found!\n", (int) numNewDevices);
}
printAllDevices();
printf("\n");
// Select a device and get its description
if(numDevices == 0) {
printf("No devices found! Please scan for new devices.\n\n");
return 1;
}
selectedDevice = &devices[0];
// Get the product description for the device
char productDescription[ICSNEO_DEVICETYPE_LONGEST_DESCRIPTION] = { 0 };
size_t descriptionLength = ICSNEO_DEVICETYPE_LONGEST_DESCRIPTION;
icsneo_describeDevice(selectedDevice, productDescription, &descriptionLength);
// Attempt to open the selected device
{
if(icsneo_openDevice(selectedDevice)) {
printf("%s successfully opened!\n\n", productDescription);
} else {
printf("%s failed to open!\n\n", productDescription);
printLastError();
printf("\n");
}
}
// Attempt to go online
{
if(icsneo_goOnline(selectedDevice)) {
printf("%s successfully went online!\n\n", productDescription);
} else {
printf("%s failed to go online!\n\n", productDescription);
printLastError();
printf("\n");
}
}
// Attempt to enable message polling
{
if(icsneo_enableMessagePolling(selectedDevice)) {
printf("Successfully enabled message polling for %s!\n\n", productDescription);
} else {
printf("Failed to enable message polling for %s!\n\n", productDescription);
printLastError();
printf("\n");
}
}
// Send message LIN
{
// Start generating sample msg
uint8_t sendMessageData[8];
sendMessageData[0] = 0x33;
sendMessageData[1] = 0x44;
sendMessageData[2] = 0x55;
sendMessageData[3] = 0x66;
sendMessageData[4] = 0x77;
sendMessageData[5] = 0x88;
sendMessageData[6] = 0x88;
neomessage_lin_t msg = {0};
msg.header[0] = 0x11; //protected ID
msg.header[1] = 0x11;
msg.header[2] = 0x22;
msg.length = 10;
msg.netid = ICSNEO_NETID_LIN;
msg.data = sendMessageData;
msg.linStatus.txCommander = 1;
msg.linStatus.txChecksumEnhanced = 1;
msg.type = ICSNEO_NETWORK_TYPE_LIN;
msg.checksum = 0x88;
// Attempt to transmit the sample msg
if(icsneo_transmit(selectedDevice, (const neomessage_t*) &msg)) {
printf("Message transmit successful!\n\n");
} else {
printf("Failed to transmit message to %s!\n\n", productDescription);
printLastError();
printf("\n");
}
}
// Wait for a moment
SLEEP(1000);
// Get messages
{
// Prepare the array of neomessage_t ptrs for reading in the messages
neomessage_t* msgs = (neomessage_t*) malloc(msgLimit * sizeof(neomessage_t));
// Get messages
size_t msgCount = msgLimit;
// Attempt to get messages
if(!icsneo_getMessages(selectedDevice, msgs, &msgCount, (uint64_t) 0)) {
printf("Failed to get messages for %s!\n\n", productDescription);
printLastError();
free(msgs);
printf("\n");
}
if(msgCount == 1) {
printf("1 message received from %s!\n", productDescription);
} else {
printf("%d messages received from %s!\n", (int) msgCount, productDescription);
}
// Print out the received messages
for(size_t i = 0; i < msgCount; i++) {
const neomessage_t* msg = &msgs[i];
switch(msg->messageType) {
case ICSNEO_MESSAGE_TYPE_FRAME: {
const neomessage_frame_t* frame = (neomessage_frame_t*)msg;
switch(frame->type) {
case ICSNEO_NETWORK_TYPE_CAN: {
neomessage_can_t* canMsg = (neomessage_can_t*)frame;
printf("\t0x%03x [%zu] ", canMsg->arbid, canMsg->length);
for(size_t i = 0; i < canMsg->length; i++) {
printf("%02x ", canMsg->data[i]);
}
if(canMsg->status.transmitMessage)
printf("TX%s %04x ", canMsg->status.globalError ? " ERR" : "", canMsg->description);
printf("(%"PRIu64")\n", canMsg->timestamp);
break;
}
case ICSNEO_NETWORK_TYPE_LIN: {
neomessage_lin_t* linMsg = (neomessage_lin_t*)frame;
size_t frameLen = linMsg->length;
size_t dataLen = (frameLen > 2) ? (frameLen - 2) : 0;
size_t numberBytesHeader = (dataLen > 1) ? 3 : 1;
size_t numberBytesData = frameLen - numberBytesHeader;
if(linMsg->netid == ICSNEO_NETID_LIN) {
printf("LIN 1 | ID: 0x%02x [%zu] ", linMsg->header[0], dataLen);
}
else if (linMsg->netid == ICSNEO_NETID_LIN2) {
printf("LIN 2 | ID: 0x%02x [%zu] ", linMsg->header[0], dataLen);
}
for(size_t i = 0; i < dataLen; ++i) {
if (i < 2) {
printf("%02x ", linMsg->header[i+1]);
} else {
printf("%02x ", linMsg->data[i-2]);
}
}
printf("| Checksum: 0x%02x\n", linMsg->checksum);
break;
}
}
break;
}
case ICSNEO_MESSAGE_TYPE_CAN_ERROR_COUNT: {
const neomessage_can_error_t* cec = (neomessage_can_error_t*)msg;
printf("\tCAN error counts changed, TEC=%d, REC=%d%s", cec->transmitErrorCount, cec->receiveErrorCount,
cec->status.canBusOff ? " (Bus Off)" : "");
break;
}
}
}
printf("\n");
free(msgs);
}
// Attempt to disable message polling
{
if(icsneo_disableMessagePolling(selectedDevice)) {
printf("Successfully disabled message polling for %s!\n\n", productDescription);
} else {
printf("Failed to disable message polling limit for %s!\n\n", productDescription);
printLastError();
printf("\n");
}
}
// Attempt to go offline
{
if(icsneo_goOffline(selectedDevice)) {
printf("%s successfully went offline!\n\n", productDescription);
} else {
printf("%s failed to go offline!\n\n", productDescription);
printLastError();
printf("\n");
}
}
// Attempt to close the device
{
if(icsneo_closeDevice(selectedDevice)) {
numDevices--;
printf("Successfully closed %s!\n\n", productDescription);
// Shifts everything after the removed device 1 index to the left
bool startResizing = false;
for(size_t i = 0; i < numDevices; ++i) {
if(selectedDevice == devices + i)
startResizing = true;
if(startResizing)
devices[i] = devices[i + 1];
}
selectedDevice = NULL;
} else {
printf("Failed to close %s!\n\n", productDescription);
printLastError();
printf("\n");
}
}
//exit
printf("Exiting program\n");
return 0;
}

View File

@ -99,7 +99,7 @@ int main() {
auto lin_r = std::make_shared<icsneo::LINMessage>(); auto lin_r = std::make_shared<icsneo::LINMessage>();
lin_r->network = icsneo::Network::NetID::LIN2; lin_r->network = icsneo::Network::NetID::LIN2;
lin_r->ID = 0x11; lin_r->ID = 0x11;
lin_r->type = icsneo::LINMessage::Type::LIN_UPDATE_RESPONDER; lin_r->linMsgType = icsneo::LINMessage::Type::LIN_UPDATE_RESPONDER;
lin_r->data = {0xaa, 0xbb, 0xcc, 0xdd, 0x11, 0x22, 0x33, 0x44}; lin_r->data = {0xaa, 0xbb, 0xcc, 0xdd, 0x11, 0x22, 0x33, 0x44};
ret = device->transmit(lin_r); // This will return false if the device does not support LIN ret = device->transmit(lin_r); // This will return false if the device does not support LIN
std::cout << (ret ? "OK" : "FAIL") << std::endl; std::cout << (ret ? "OK" : "FAIL") << std::endl;
@ -108,7 +108,7 @@ int main() {
auto lin_c = std::make_shared<icsneo::LINMessage>(); auto lin_c = std::make_shared<icsneo::LINMessage>();
lin_c->network = icsneo::Network::NetID::LIN; lin_c->network = icsneo::Network::NetID::LIN;
lin_c->ID = 0x11; lin_c->ID = 0x11;
lin_c->type = icsneo::LINMessage::Type::LIN_HEADER_ONLY; lin_c->linMsgType = icsneo::LINMessage::Type::LIN_HEADER_ONLY;
ret = device->transmit(lin_c); ret = device->transmit(lin_c);
std::cout << (ret ? "OK" : "FAIL") << std::endl << std::endl; std::cout << (ret ? "OK" : "FAIL") << std::endl << std::endl;
@ -117,7 +117,7 @@ int main() {
lin_d->network = icsneo::Network::NetID::LIN; lin_d->network = icsneo::Network::NetID::LIN;
lin_d->ID = 0x22; lin_d->ID = 0x22;
lin_d->isEnhancedChecksum = true; lin_d->isEnhancedChecksum = true;
lin_d->type = icsneo::LINMessage::Type::LIN_COMMANDER_MSG; lin_d->linMsgType = icsneo::LINMessage::Type::LIN_COMMANDER_MSG;
lin_d->data = {0x11, 0x22, 0x33, 0x44, 0xaa, 0xbb, 0xcc, 0xdd}; lin_d->data = {0x11, 0x22, 0x33, 0x44, 0xaa, 0xbb, 0xcc, 0xdd};
ret = device->transmit(lin_d); ret = device->transmit(lin_d);
std::cout << (ret ? "OK" : "FAIL") << std::endl << std::endl; std::cout << (ret ? "OK" : "FAIL") << std::endl << std::endl;

View File

@ -36,10 +36,8 @@ struct LINStatusFlags {
class LINMessage : public Frame { class LINMessage : public Frame {
public: public:
static void calcChecksum(LINMessage& message); enum class Type : uint8_t {
NOT_SET = 0,
enum class Type {
NOT_SET,
LIN_COMMANDER_MSG, LIN_COMMANDER_MSG,
LIN_HEADER_ONLY, LIN_HEADER_ONLY,
LIN_BREAK_ONLY, LIN_BREAK_ONLY,
@ -48,12 +46,17 @@ public:
LIN_ERROR LIN_ERROR
}; };
static void calcChecksum(LINMessage& message);
uint8_t calcProtectedID(uint8_t& id);
LINMessage() {};
LINMessage(uint8_t id) : ID(id & 0x3Fu), protectedID(calcProtectedID(ID)) {};
uint8_t ID = 0; uint8_t ID = 0;
uint8_t protectedID = 0; uint8_t protectedID = 0;
uint8_t checksum = 0; uint8_t checksum = 0;
LINMessage::Type type = Type::NOT_SET; LINMessage::Type linMsgType = Type::NOT_SET;
bool isEnhancedChecksum = false; bool isEnhancedChecksum = false;
bool isLINStd2x = true;
LINErrorFlags errFlags; LINErrorFlags errFlags;
LINStatusFlags statusFlags; LINStatusFlags statusFlags;
}; };

View File

@ -86,14 +86,24 @@ typedef union {
// ethernetFrameTooShort // ethernetFrameTooShort
// ethernetFCSAvailable // ethernetFCSAvailable
// ~~~ End of bitfield 2 ~~~ // ~~~ End of bitfield 2 ~~~
//uint32_t linJustBreakSync : 1; union {
//uint32_t linSlaveDataTooShort : 1; uint32_t status3;
//uint32_t linOnlyUpdateSlaveTableOnce : 1; struct {
uint32_t canfdESI : 1; uint32_t canfdESI : 1;
uint32_t canfdIDE : 1; uint32_t canfdIDE : 1;
uint32_t canfdRTR : 1; uint32_t canfdRTR : 1;
uint32_t canfdFDF : 1; uint32_t canfdFDF : 1;
uint32_t canfdBRS : 1; uint32_t canfdBRS : 1;
uint32_t : 27;
};
struct {
uint32_t linJustBreakSync : 1;
uint32_t linSlaveDataTooShort : 1;
uint32_t linOnlyUpdateSlaveTableOnce : 1;
uint32_t : 29;
};
};
}; };
uint32_t statusBitfield[4]; uint32_t statusBitfield[4];
} neomessage_statusbitfield_t; } neomessage_statusbitfield_t;
@ -171,6 +181,33 @@ typedef struct {
uint8_t _reserved1[12]; uint8_t _reserved1[12];
} neomessage_eth_t; } neomessage_eth_t;
typedef struct {
uint8_t txChecksumEnhanced : 1;
uint8_t txCommander : 1;
uint8_t txResponder : 1;
uint8_t txAborted : 1;
uint8_t updateResponderOnce : 1;
uint8_t hasUpdatedResponderOnce : 1;
uint8_t busRecovered : 1;
uint8_t breakOnly : 1;
} neomessage_linstatus_t;
typedef struct {
neomessage_statusbitfield_t status;
uint64_t timestamp;
uint64_t _reservedTimestamp;
const uint8_t* data;
size_t length;
uint8_t header[4];
neonetid_t netid;
neonettype_t type;
neomessage_linstatus_t linStatus;
uint16_t description;
neomessagetype_t messageType;
uint8_t checksum;
uint8_t _reserved1[11];
} neomessage_lin_t;
#pragma pack(pop) #pragma pack(pop)
#ifdef __cplusplus #ifdef __cplusplus
@ -182,6 +219,7 @@ static_assert(sizeof(neomessage_frame_t) == sizeof(neomessage_t), "All types of
static_assert(sizeof(neomessage_can_t) == sizeof(neomessage_t), "All types of neomessage_t must be the same size! (CAN is not)"); static_assert(sizeof(neomessage_can_t) == sizeof(neomessage_t), "All types of neomessage_t must be the same size! (CAN is not)");
static_assert(sizeof(neomessage_can_error_t) == sizeof(neomessage_t), "All types of neomessage_t must be the same size! (CAN error is not)"); static_assert(sizeof(neomessage_can_error_t) == sizeof(neomessage_t), "All types of neomessage_t must be the same size! (CAN error is not)");
static_assert(sizeof(neomessage_eth_t) == sizeof(neomessage_t), "All types of neomessage_t must be the same size! (Ethernet is not)"); static_assert(sizeof(neomessage_eth_t) == sizeof(neomessage_t), "All types of neomessage_t must be the same size! (Ethernet is not)");
static_assert(sizeof(neomessage_lin_t) == sizeof(neomessage_t), "All types of neomessage_t must be the same size! (LIN is not)");
namespace icsneo { namespace icsneo {

View File

@ -86,10 +86,9 @@ std::vector<uint8_t> testControllerWithData =
TEST_F(LINEncoderDecoderTest, ProtectedIDCalcTest) { TEST_F(LINEncoderDecoderTest, ProtectedIDCalcTest) {
std::vector<uint8_t> bytestream; std::vector<uint8_t> bytestream;
auto message = std::make_shared<icsneo::LINMessage>(); auto message = std::make_shared<icsneo::LINMessage>(static_cast<uint8_t>(0x22u));
message->network = icsneo::Network::NetID::LIN; message->network = icsneo::Network::NetID::LIN;
message->ID = 0x22; message->linMsgType = icsneo::LINMessage::Type::LIN_UPDATE_RESPONDER;
message->type = icsneo::LINMessage::Type::LIN_UPDATE_RESPONDER;
message->isEnhancedChecksum = false; message->isEnhancedChecksum = false;
packetEncoder->encode(*packetizer, bytestream, message); packetEncoder->encode(*packetizer, bytestream, message);
EXPECT_EQ(message->protectedID, 0xE2); EXPECT_EQ(message->protectedID, 0xE2);
@ -97,10 +96,9 @@ TEST_F(LINEncoderDecoderTest, ProtectedIDCalcTest) {
TEST_F(LINEncoderDecoderTest, ChecksumCalcTestClassic) { TEST_F(LINEncoderDecoderTest, ChecksumCalcTestClassic) {
std::vector<uint8_t> bytestream; std::vector<uint8_t> bytestream;
auto message = std::make_shared<icsneo::LINMessage>(); auto message = std::make_shared<icsneo::LINMessage>(static_cast<uint8_t>(0x22u));
message->network = icsneo::Network::NetID::LIN2; message->network = icsneo::Network::NetID::LIN2;
message->ID = 0x22; message->linMsgType = icsneo::LINMessage::Type::LIN_UPDATE_RESPONDER;
message->type = icsneo::LINMessage::Type::LIN_UPDATE_RESPONDER;
message->isEnhancedChecksum = false; message->isEnhancedChecksum = false;
message->data = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}; message->data = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
packetEncoder->encode(*packetizer, bytestream, message); packetEncoder->encode(*packetizer, bytestream, message);
@ -109,10 +107,9 @@ TEST_F(LINEncoderDecoderTest, ChecksumCalcTestClassic) {
TEST_F(LINEncoderDecoderTest, ChecksumCalcTestEnhanced) { TEST_F(LINEncoderDecoderTest, ChecksumCalcTestEnhanced) {
std::vector<uint8_t> bytestream; std::vector<uint8_t> bytestream;
auto message = std::make_shared<icsneo::LINMessage>(); auto message = std::make_shared<icsneo::LINMessage>(static_cast<uint8_t>(0x22u));
message->network = icsneo::Network::NetID::LIN2; message->network = icsneo::Network::NetID::LIN2;
message->ID = 0x22; message->linMsgType = icsneo::LINMessage::Type::LIN_UPDATE_RESPONDER;
message->type = icsneo::LINMessage::Type::LIN_UPDATE_RESPONDER;
message->isEnhancedChecksum = true; message->isEnhancedChecksum = true;
message->data = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}; message->data = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
packetEncoder->encode(*packetizer, bytestream, message); packetEncoder->encode(*packetizer, bytestream, message);
@ -121,10 +118,9 @@ TEST_F(LINEncoderDecoderTest, ChecksumCalcTestEnhanced) {
TEST_F(LINEncoderDecoderTest, PacketEncoderResponderLoadTest) { TEST_F(LINEncoderDecoderTest, PacketEncoderResponderLoadTest) {
std::vector<uint8_t> bytestream; std::vector<uint8_t> bytestream;
auto message = std::make_shared<icsneo::LINMessage>(); auto message = std::make_shared<icsneo::LINMessage>(static_cast<uint8_t>(0x22u));
message->network = icsneo::Network::NetID::LIN2; message->network = icsneo::Network::NetID::LIN2;
message->ID = 0x22; message->linMsgType = icsneo::LINMessage::Type::LIN_UPDATE_RESPONDER;
message->type = icsneo::LINMessage::Type::LIN_UPDATE_RESPONDER;
message->isEnhancedChecksum = false; message->isEnhancedChecksum = false;
message->data = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}; message->data = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
packetEncoder->encode(*packetizer, bytestream, message); packetEncoder->encode(*packetizer, bytestream, message);
@ -133,10 +129,9 @@ TEST_F(LINEncoderDecoderTest, PacketEncoderResponderLoadTest) {
TEST_F(LINEncoderDecoderTest, PacketEncoderControllerHeaderTest) { TEST_F(LINEncoderDecoderTest, PacketEncoderControllerHeaderTest) {
std::vector<uint8_t> bytestream; std::vector<uint8_t> bytestream;
auto message = std::make_shared<icsneo::LINMessage>(); auto message = std::make_shared<icsneo::LINMessage>(static_cast<uint8_t>(0x22u));
message->network = icsneo::Network::NetID::LIN; message->network = icsneo::Network::NetID::LIN;
message->ID = 0x22; message->linMsgType = icsneo::LINMessage::Type::LIN_HEADER_ONLY;
message->type = icsneo::LINMessage::Type::LIN_HEADER_ONLY;
message->isEnhancedChecksum = false; message->isEnhancedChecksum = false;
packetEncoder->encode(*packetizer, bytestream, message); packetEncoder->encode(*packetizer, bytestream, message);
EXPECT_EQ(bytestream, testControllerHeaderOnly); EXPECT_EQ(bytestream, testControllerHeaderOnly);
@ -144,10 +139,9 @@ TEST_F(LINEncoderDecoderTest, PacketEncoderControllerHeaderTest) {
TEST_F(LINEncoderDecoderTest, PacketEncoderControllerWithDataTest) { TEST_F(LINEncoderDecoderTest, PacketEncoderControllerWithDataTest) {
std::vector<uint8_t> bytestream; std::vector<uint8_t> bytestream;
auto message = std::make_shared<icsneo::LINMessage>(); auto message = std::make_shared<icsneo::LINMessage>(static_cast<uint8_t>(0x11u));
message->network = icsneo::Network::NetID::LIN; message->network = icsneo::Network::NetID::LIN;
message->ID = 0x11; message->linMsgType = icsneo::LINMessage::Type::LIN_COMMANDER_MSG;
message->type = icsneo::LINMessage::Type::LIN_COMMANDER_MSG;
message->isEnhancedChecksum = false; message->isEnhancedChecksum = false;
message->data = {0xaa, 0xbb, 0xcc}; message->data = {0xaa, 0xbb, 0xcc};
packetEncoder->encode(*packetizer, bytestream, message); packetEncoder->encode(*packetizer, bytestream, message);
@ -156,19 +150,17 @@ TEST_F(LINEncoderDecoderTest, PacketEncoderControllerWithDataTest) {
TEST_F(LINEncoderDecoderTest, PacketDecoderTest) { TEST_F(LINEncoderDecoderTest, PacketDecoderTest) {
std::shared_ptr<icsneo::Message> decodeMsg; std::shared_ptr<icsneo::Message> decodeMsg;
auto msg1 = std::make_shared<icsneo::LINMessage>();
auto msg2 = std::make_shared<icsneo::LINMessage>();
auto msg1 = std::make_shared<icsneo::LINMessage>(static_cast<uint8_t>(0x22u));
msg1->network = icsneo::Network::NetID::LIN2; msg1->network = icsneo::Network::NetID::LIN2;
msg1->ID = 0x22; msg1->linMsgType = icsneo::LINMessage::Type::LIN_COMMANDER_MSG;
msg1->type = icsneo::LINMessage::Type::LIN_COMMANDER_MSG;
msg1->isEnhancedChecksum = false; msg1->isEnhancedChecksum = false;
msg1->data = {0xaa, 0xbb, 0xcc}; msg1->data = {0xaa, 0xbb, 0xcc};
msg1->checksum = 0xcc; msg1->checksum = 0xcc;
auto msg2 = std::make_shared<icsneo::LINMessage>(static_cast<uint8_t>(0x22u));
msg2->network = icsneo::Network::NetID::LIN; msg2->network = icsneo::Network::NetID::LIN;
msg2->ID = 0x22; msg2->linMsgType = icsneo::LINMessage::Type::LIN_COMMANDER_MSG;
msg2->type = icsneo::LINMessage::Type::LIN_COMMANDER_MSG;
msg2->isEnhancedChecksum = false; msg2->isEnhancedChecksum = false;
msg2->data = {0xaa, 0xbb, 0xcc}; msg2->data = {0xaa, 0xbb, 0xcc};
msg2->checksum = 0xcc; msg2->checksum = 0xcc;