From f63c187ed38dd1d0ee057f3c12325acb129f542b Mon Sep 17 00:00:00 2001 From: Paul Hollinsky Date: Thu, 18 Feb 2021 23:19:33 -0500 Subject: [PATCH] Add receive support for ISO 9141-2 --- CMakeLists.txt | 1 + communication/decoder.cpp | 17 +++++ communication/packet/iso9141packet.cpp | 64 +++++++++++++++++++ examples/cpp/simple/src/SimpleExample.cpp | 24 +++++++ include/icsneo/communication/decoder.h | 2 + .../communication/message/iso9141message.h | 29 +++++++++ include/icsneo/communication/network.h | 43 ++++++++----- .../communication/packet/iso9141packet.h | 56 ++++++++++++++++ include/icsneo/icsneocpp.h | 2 + 9 files changed, 222 insertions(+), 16 deletions(-) create mode 100644 communication/packet/iso9141packet.cpp create mode 100644 include/icsneo/communication/message/iso9141message.h create mode 100644 include/icsneo/communication/packet/iso9141packet.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 74db8c1..7045633 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -122,6 +122,7 @@ set(SRC_FILES communication/packet/flexraypacket.cpp communication/packet/canpacket.cpp communication/packet/ethernetpacket.cpp + communication/packet/iso9141packet.cpp communication/decoder.cpp communication/encoder.cpp communication/ethernetpacketizer.cpp diff --git a/communication/decoder.cpp b/communication/decoder.cpp index cd9b5cd..cf04622 100644 --- a/communication/decoder.cpp +++ b/communication/decoder.cpp @@ -9,6 +9,7 @@ #include "icsneo/communication/packet/canpacket.h" #include "icsneo/communication/packet/ethernetpacket.h" #include "icsneo/communication/packet/flexraypacket.h" +#include "icsneo/communication/packet/iso9141packet.h" #include using namespace icsneo; @@ -70,6 +71,22 @@ bool Decoder::decode(std::shared_ptr& result, const std::shared_ptrnetwork = packet->network; return true; } + case Network::Type::ISO9141: { + if(packet->data.size() < sizeof(HardwareISO9141Packet)) { + report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error); + return false; + } + + result = iso9141decoder.decodeToMessage(packet->data); + if(!result) + return false; // A nullptr was returned, more data is required to decode this packet + + // Timestamps are in (resolution) ns increments since 1/1/2007 GMT 00:00:00.0000 + // The resolution depends on the device + result->timestamp *= timestampResolution; + result->network = packet->network; + return true; + } case Network::Type::Internal: { switch(packet->network.getNetID()) { case Network::NetID::Reset_Status: { diff --git a/communication/packet/iso9141packet.cpp b/communication/packet/iso9141packet.cpp new file mode 100644 index 0000000..56438ec --- /dev/null +++ b/communication/packet/iso9141packet.cpp @@ -0,0 +1,64 @@ +#include "icsneo/communication/packet/iso9141packet.h" +#include + +using namespace icsneo; + +std::shared_ptr HardwareISO9141Packet::Decoder::decodeToMessage(const std::vector& bytestream) { + const HardwareISO9141Packet* data = (const HardwareISO9141Packet*)bytestream.data(); + + if(!mMsg) { + mMsg = std::make_shared(); + mGotPackets = 0; + } + + mGotPackets++; + + const bool morePacketsComing = data->c3.frm == 0; + const uint8_t bytesInCurrentMessage = data->c3.len; + if(mMsg->data.size() + bytesInCurrentMessage > 500) { + mMsg.reset(); + return std::shared_ptr(); + } + + // This timestamp is raw off the device (in timestampResolution increments) + // Decoder will fix as it has information about the timestampResolution increments + mMsg->timestamp = data->timestamp.TS; + + auto* dataStart = data->data; + if(mGotPackets == 1) { + // Header + if(bytesInCurrentMessage < 3) { + mMsg.reset(); // We don't have the header for some reason + return std::shared_ptr(); + } + + std::copy(data->data, data->data + 3, mMsg->header.begin()); + dataStart += 3; + } + + // Data + mMsg->data.insert(mMsg->data.end(), dataStart, data->data + (bytesInCurrentMessage > 8 ? 8 : bytesInCurrentMessage)); + if(bytesInCurrentMessage > 8) + mMsg->data.push_back(data->c1.d8); + if(bytesInCurrentMessage > 9) + mMsg->data.push_back(data->c2.d9); + if(bytesInCurrentMessage > 10) + mMsg->data.push_back(data->c2.d10); + if(bytesInCurrentMessage > 11) + mMsg->data.push_back(data->c3.d11); + + if(morePacketsComing) + return std::shared_ptr(); + + mMsg->transmitted = data->c1.tx; + mMsg->isInit = data->c3.init; + mMsg->framingError = data->c1.options & 0x1; + mMsg->overflowError = data->c1.options & 0x2; + mMsg->parityError = data->c1.options & 0x4; + mMsg->rxTimeoutError = data->c1.options & 0x8; + mMsg->description = data->stats; + + auto ret = mMsg; + mMsg.reset(); + return ret; +} \ No newline at end of file diff --git a/examples/cpp/simple/src/SimpleExample.cpp b/examples/cpp/simple/src/SimpleExample.cpp index cd9a647..e840b9a 100644 --- a/examples/cpp/simple/src/SimpleExample.cpp +++ b/examples/cpp/simple/src/SimpleExample.cpp @@ -176,6 +176,30 @@ int main() { std::cout << std::dec << std::endl; break; } + case icsneo::Network::Type::ISO9141: { + // Note that the default settings on some devices have ISO9141 disabled by default in favor of LIN + // and that this example loads the device defaults at the very end. + // A message of type ISO9414 is guaranteed to be an ISO9141Message, so we can static cast safely + auto isoMessage = std::static_pointer_cast(message); + + std::cout << "\t\tISO 9141-2 "; + + // Print the header bytes + std::cout << '(' << std::hex << std::setfill('0') << std::setw(2) << (uint32_t)isoMessage->header[0] << ' '; + std::cout << std::setfill('0') << std::setw(2) << (uint32_t)isoMessage->header[1] << ' '; + std::cout << std::setfill('0') << std::setw(2) << (uint32_t)isoMessage->header[2] << ") "; + + // Print the data length + std::cout << std::dec << " [" << isoMessage->data.size() << "] "; + + // Print the data + for(auto& databyte : isoMessage->data) + std::cout << std::hex << std::setfill('0') << std::setw(2) << (uint32_t)databyte << ' '; + + // Print the timestamp + std::cout << std::dec << '(' << isoMessage->timestamp << " ns since 1/1/2007)\n"; + break; + } default: // Ignoring non-network messages break; diff --git a/include/icsneo/communication/decoder.h b/include/icsneo/communication/decoder.h index dd5792e..fa2f9e7 100644 --- a/include/icsneo/communication/decoder.h +++ b/include/icsneo/communication/decoder.h @@ -7,6 +7,7 @@ #include "icsneo/communication/message/canmessage.h" #include "icsneo/communication/packet.h" #include "icsneo/communication/network.h" +#include "icsneo/communication/packet/iso9141packet.h" #include "icsneo/api/eventmanager.h" #include #include @@ -25,6 +26,7 @@ public: private: device_eventhandler_t report; + HardwareISO9141Packet::Decoder iso9141decoder; #pragma pack(push, 1) diff --git a/include/icsneo/communication/message/iso9141message.h b/include/icsneo/communication/message/iso9141message.h new file mode 100644 index 0000000..bd091d3 --- /dev/null +++ b/include/icsneo/communication/message/iso9141message.h @@ -0,0 +1,29 @@ +#ifndef __ISO9141MESSAGE_H_ +#define __ISO9141MESSAGE_H_ + +#ifdef __cplusplus + +#include "icsneo/communication/message/message.h" +#include + +namespace icsneo { + +class ISO9141Message : public Message { +public: + std::array header; + bool isInit = false; + bool framingError = false; + bool overflowError = false; + bool parityError = false; + bool rxTimeoutError = false; + // Checksum not yet implemted, it's just at the end of the data if enabled for now + // bool checksumError = false; + // bool hasChecksum = false; + // uint8_t checksum = 0; +}; + +} + +#endif // __cplusplus + +#endif \ No newline at end of file diff --git a/include/icsneo/communication/network.h b/include/icsneo/communication/network.h index 2292584..d731a00 100644 --- a/include/icsneo/communication/network.h +++ b/include/icsneo/communication/network.h @@ -20,12 +20,12 @@ public: J1708 = 6, Aux = 7, J1850VPW = 8, - ISO = 9, + ISO9141 = 9, ISOPIC = 10, Main51 = 11, RED = 12, SCI = 13, - ISO2 = 14, + ISO9141_2 = 14, ISO14230 = 15, LIN = 16, OP_Ethernet1 = 17, @@ -57,12 +57,12 @@ public: RED_GET_RTC = 40, // END Device Command Returns - ISO3 = 41, + ISO9141_3 = 41, HSCAN2 = 42, HSCAN3 = 44, OP_Ethernet4 = 45, OP_Ethernet5 = 46, - ISO4 = 47, + ISO9141_4 = 47, LIN2 = 48, LIN3 = 49, LIN4 = 50, @@ -132,6 +132,7 @@ public: Ethernet = 6, LSFTCAN = 7, SWCAN = 8, + ISO9141 = 9, Any = 0xFE, // Never actually set as type, but used as flag for filtering Other = 0xFF }; @@ -149,6 +150,8 @@ public: return "Other"; case Type::Internal: return "Internal"; + case Type::ISO9141: + return "ISO 9141-2"; case Type::Ethernet: return "Ethernet"; case Type::LSFTCAN: @@ -219,6 +222,11 @@ public: case NetID::SWCAN: case NetID::SWCAN2: return Type::SWCAN; + case NetID::ISO9141: + case NetID::ISO9141_2: + case NetID::ISO9141_3: + case NetID::ISO9141_4: + return Type::ISO9141; default: return Type::Other; } @@ -243,8 +251,8 @@ public: return "Aux"; case NetID::J1850VPW: return "J1850 VPW"; - case NetID::ISO: - return "ISO"; + case NetID::ISO9141: + return "ISO 9141"; case NetID::ISOPIC: return "ISOPIC"; case NetID::Main51: @@ -253,8 +261,8 @@ public: return "RED"; case NetID::SCI: return "SCI"; - case NetID::ISO2: - return "ISO 2"; + case NetID::ISO9141_2: + return "ISO 9141 2"; case NetID::ISO14230: return "ISO 14230"; case NetID::LIN: @@ -307,8 +315,8 @@ public: return "RED_HARDWARE_EXCEP"; case NetID::RED_GET_RTC: return "RED_GET_RTC"; - case NetID::ISO3: - return "ISO 3"; + case NetID::ISO9141_3: + return "ISO 9141 3"; case NetID::HSCAN2: return "HSCAN 2"; case NetID::HSCAN3: @@ -317,8 +325,8 @@ public: return "OP (BR) Ethernet 4"; case NetID::OP_Ethernet5: return "OP (BR) Ethernet 5"; - case NetID::ISO4: - return "ISO 4"; + case NetID::ISO9141_4: + return "ISO 9141 4"; case NetID::LIN2: return "LIN 2"; case NetID::LIN3: @@ -471,12 +479,12 @@ private: #define ICSNEO_NETID_J1708 6 #define ICSNEO_NETID_AUX 7 #define ICSNEO_NETID_J1850VPW 8 -#define ICSNEO_NETID_ISO 9 +#define ICSNEO_NETID_ISO9141 9 #define ICSNEO_NETID_ISOPIC 10 #define ICSNEO_NETID_MAIN51 11 #define ICSNEO_NETID_RED 12 #define ICSNEO_NETID_SCI 13 -#define ICSNEO_NETID_ISO2 14 +#define ICSNEO_NETID_ISO9141_2 14 #define ICSNEO_NETID_ISO14230 15 #define ICSNEO_NETID_LIN 16 #define ICSNEO_NETID_OP_ETHERNET1 17 @@ -508,12 +516,12 @@ private: #define ICSNEO_NETID_RED_GET_RTC 40 // END Device Command Returns -#define ICSNEO_NETID_ISO3 41 +#define ICSNEO_NETID_ISO9141_3 41 #define ICSNEO_NETID_HSCAN2 42 #define ICSNEO_NETID_HSCAN3 44 #define ICSNEO_NETID_OP_ETHERNET4 45 #define ICSNEO_NETID_OP_ETHERNET5 46 -#define ICSNEO_NETID_ISO4 47 +#define ICSNEO_NETID_ISO9141_4 47 #define ICSNEO_NETID_LIN2 48 #define ICSNEO_NETID_LIN3 49 #define ICSNEO_NETID_LIN4 50 @@ -579,6 +587,9 @@ private: #define ICSNEO_NETWORK_TYPE_FLEXRAY 4 #define ICSNEO_NETWORK_TYPE_MOST 5 #define ICSNEO_NETWORK_TYPE_ETHERNET 6 +#define ICSNEO_NETWORK_TYPE_LSFTCAN 7 +#define ICSNEO_NETWORK_TYPE_SWCAN 8 +#define ICSNEO_NETWORK_TYPE_ISO9141 9 #define ICSNEO_NETWORK_TYPE_ANY 0xFE // Never actually set as type, but used as flag for filtering #define ICSNEO_NETWORK_TYPE_OTHER 0xFF #endif diff --git a/include/icsneo/communication/packet/iso9141packet.h b/include/icsneo/communication/packet/iso9141packet.h new file mode 100644 index 0000000..ae8b3aa --- /dev/null +++ b/include/icsneo/communication/packet/iso9141packet.h @@ -0,0 +1,56 @@ +#ifndef __ISO9141PACKET_H__ +#define __ISO9141PACKET_H__ + +#ifdef __cplusplus + +#include "icsneo/communication/message/iso9141message.h" +#include "icsneo/api/eventmanager.h" +#include +#include +#include + +namespace icsneo { + +typedef uint16_t icscm_bitfield; + +struct HardwareISO9141Packet { + class Decoder { + public: + std::shared_ptr decodeToMessage(const std::vector& bytestream); + private: + std::shared_ptr mMsg; + size_t mGotPackets = 0; + }; + + struct { + icscm_bitfield d8 : 8; + icscm_bitfield options : 4; + icscm_bitfield tx : 1; + icscm_bitfield networkIndex : 3; + } c1; + struct { + icscm_bitfield d9 : 8; + icscm_bitfield d10 : 8; + } c2; + struct { + icscm_bitfield len : 4; + icscm_bitfield extendedNetworkIndexBit2 : 1; + icscm_bitfield frm : 1; + icscm_bitfield init : 1; + icscm_bitfield extendedNetworkIndexBit : 1; + icscm_bitfield d11 : 8; + } c3; + unsigned char data[8]; + uint16_t stats; + struct { + uint64_t TS : 60; + uint64_t : 3; // Reserved for future status bits + uint64_t IsExtended : 1; + } timestamp; +}; + +} + +#endif // __cplusplus + +#endif \ No newline at end of file diff --git a/include/icsneo/icsneocpp.h b/include/icsneo/icsneocpp.h index a21903e..f0847bc 100644 --- a/include/icsneo/icsneocpp.h +++ b/include/icsneo/icsneocpp.h @@ -12,6 +12,8 @@ #include "icsneo/communication/message/canmessage.h" #include "icsneo/communication/message/ethernetmessage.h" +#include "icsneo/communication/message/flexray/flexraymessage.h" +#include "icsneo/communication/message/iso9141message.h" namespace icsneo {