From 5d4cfe49301effe36d666e74d1237eb4122a2de9 Mon Sep 17 00:00:00 2001 From: Paul Hollinsky Date: Wed, 10 Oct 2018 16:25:09 -0400 Subject: [PATCH] Decoding for CAN FD, RTR, and XTD ID --- communication/decoder.cpp | 73 ++++++- communication/include/decoder.h | 220 +-------------------- communication/message/include/canmessage.h | 4 + communication/message/include/neomessage.h | 93 ++++++++- communication/message/neomessage.cpp | 12 +- 5 files changed, 177 insertions(+), 225 deletions(-) diff --git a/communication/decoder.cpp b/communication/decoder.cpp index 154ec38..c45d78e 100644 --- a/communication/decoder.cpp +++ b/communication/decoder.cpp @@ -24,14 +24,79 @@ std::shared_ptr Decoder::decodePacket(const std::shared_ptr& pa HardwareCANPacket* data = (HardwareCANPacket*)packet->data.data(); auto msg = std::make_shared(); msg->network = packet->network; - msg->arbid = data->header.SID; - msg->data.reserve(data->dlc.DLC); // Timestamp calculation msg->timestamp = data->timestamp.TS * 25; // Timestamps are in 25ns increments since 1/1/2007 GMT 00:00:00.0000 - for(auto i = 0; i < data->dlc.DLC; i++) - msg->data.push_back(data->data[i]); + // Arb ID + if(data->header.IDE) { // Extended 29-bit ID + msg->arbid = (data->header.SID & 0x7ff) << 18; + msg->arbid |= (data->eid.EID & 0xfff) << 6; + msg->arbid |= (data->dlc.EID2 & 0x3f); + msg->isExtended = true; + } else { // Standard 11-bit ID + msg->arbid = data->header.SID; + } + + // DLC + uint8_t length = data->dlc.DLC; + if(data->header.EDL && data->timestamp.IsExtended) { // CAN FD + msg->isCANFD = true; + msg->baudrateSwitch = data->header.BRS; // CAN FD Baudrate Switch + switch(length) { // CAN FD Length Decoding + case 0x0: + case 0x1: + case 0x2: + case 0x3: + case 0x4: + case 0x5: + case 0x6: + case 0x7: + case 0x8: + break; // The length is already correct + case 0x9: + length = 12; + break; + case 0xa: + length = 16; + break; + case 0xb: + length = 20; + break; + case 0xc: + length = 24; + break; + case 0xd: + length = 32; + break; + case 0xe: + length = 48; + break; + case 0xf: + length = 64; + break; + default: + length = 0; + // TODO Flag an error + break; + } + } + + // Data + // The first 8 bytes are always in the standard place + if(data->dlc.RTR) { // Remote Request Frame + msg->data.resize(length); // This data will be all zeros, but the length will be set + msg->isRemote = true; + } else { + msg->data.reserve(length); + msg->data.insert(msg->data.end(), data->data, data->data + (length > 8 ? 8 : length)); + if(length > 8) { // If there are more than 8 bytes, they come at the end of the message + // Messages with extra data are formatted as message, then uint16_t netid, then uint16_t length, then extra data + uint8_t* extraDataStart = packet->data.data() + sizeof(HardwareCANPacket) + 2 + 2; + msg->data.insert(msg->data.end(), extraDataStart, extraDataStart + (length - 8)); + } + } + return msg; } case Network::Type::Internal: { diff --git a/communication/include/decoder.h b/communication/include/decoder.h index fa6cb72..d628999 100644 --- a/communication/include/decoder.h +++ b/communication/include/decoder.h @@ -44,12 +44,13 @@ private: icscm_bitfield ExtendedNetworkIndexBit : 1;//DO NOT CLOBBER THIS icscm_bitfield RB1 : 1; icscm_bitfield RTR : 1; - icscm_bitfield EID : 6; + icscm_bitfield EID2 : 6; } dlc; unsigned char data[8]; + uint16_t stats; struct { uint64_t TS : 60; - uint64_t : 3; + uint64_t : 3; // Reserved for future status bits uint64_t IsExtended : 1; } timestamp; }; @@ -87,221 +88,6 @@ private: uint16_t busVoltage; uint16_t deviceTemperature; } CoreMiniMsgResetStatus; - - // struct CoreMiniMsg { - // CANMessage toCANMessage(Network netid); - // union { - // uint16_t CxTRB0SID16; - // struct - // { - // icscm_bitfield IDE : 1; - // icscm_bitfield SRR : 1; - // icscm_bitfield SID : 11; - // icscm_bitfield NETWORKINDEX : 3;//DO NOT CLOBBER THIS - // } CxTRB0SID; - // struct - // { - // icscm_bitfield : 13; - // icscm_bitfield EDL : 1; - // icscm_bitfield BRS : 1; - // icscm_bitfield ESI : 1; - // } CxTRB0FD; - // struct - // { - // icscm_bitfield ErrRxOnlyBreak : 1; - // icscm_bitfield ErrRxOnlyBreakSync : 1; - // icscm_bitfield ID : 11; - // icscm_bitfield NETWORKINDEX : 3;//DO NOT CLOBBER THIS - // } CxLIN3; - // struct - // { - // uint8_t D8; - // uint8_t options : 4; - // uint8_t TXMSG : 1; - // uint8_t NETWORKINDEX : 3;//DO NOT CLOBBER THIS - // } C1xJ1850; - // struct - // { - // uint8_t D8; - // uint8_t options : 4; - // uint8_t TXMSG : 1; - // uint8_t NETWORKINDEX : 3;//DO NOT CLOBBER THIS - // } C1xISO; - // struct - // { - // uint8_t D8; - // uint8_t options : 4; - // uint8_t TXMSG : 1; - // uint8_t NETWORKINDEX : 3;//DO NOT CLOBBER THIS - // } C1xJ1708; - // struct - // { - // icscm_bitfield FCS_AVAIL : 1; - // icscm_bitfield RUNT_FRAME : 1; - // icscm_bitfield DISABLE_PADDING : 1; - // icscm_bitfield PREEMPTION_ENABLED : 1; - // icscm_bitfield MPACKET_TYPE : 4; - // icscm_bitfield MPACKET_FRAG_CNT : 2; - // icscm_bitfield : 6; - // } C1xETH; - // struct - // { - // uint16_t ID : 11; - // uint16_t STARTUP : 1; - // uint16_t SYNC : 1; - // uint16_t NULL_FRAME : 1; - // uint16_t PAYLOAD_PREAMBLE : 1; - // uint16_t RESERVED_0 : 1; - // } C1xFlex; - // struct - // { - // uint8_t daqType; - // uint8_t ethDaqRes1; - // } C1xETHDAQ; - // }; - // union { - // uint16_t CxTRB0EID16; - // struct - // { - // icscm_bitfield EID : 12; - // icscm_bitfield TXMSG : 1; - // icscm_bitfield TXAborted : 1; - // icscm_bitfield TXLostArb : 1; - // icscm_bitfield TXError : 1; - // } CxTRB0EID; - // struct - // { - // uint8_t LINByte9; - // uint8_t ErrTxRxMismatch : 1; - // uint8_t TxChkSumEnhanced : 1; - // uint8_t TXMaster : 1; - // uint8_t TXSlave : 1; - // uint8_t ErrRxBreakNot0 : 1; - // uint8_t ErrRxBreakTooShort : 1; - // uint8_t ErrRxSyncNot55 : 1; - // uint8_t ErrRxDataGreater8 : 1; - // } CxLIN; - // struct - // { - // uint8_t D9; - // uint8_t D10; - // } C2xJ1850; - // struct - // { - // uint8_t D9; - // uint8_t D10; - // } C2xISO; - // struct - // { - // uint8_t D9; - // uint8_t D10; - // } C2xJ1708; - // struct - // { - // uint16_t txlen : 12; - // uint16_t TXMSG : 1; - // uint16_t : 3; - // } C2xETH; - // struct - // { - // uint16_t HDR_CRC_10 : 1; - // uint16_t PAYLOAD_LEN : 7; - // uint16_t RESERVED_1 : 4; - // uint16_t TXMSG : 1; - // uint16_t RESERVED_2 : 3; - // } C2xFlex; - // }; - // union { - // // For use by CAN - // uint16_t CxTRB0DLC16; - // struct - // { - // icscm_bitfield DLC : 4; - // icscm_bitfield RB0 : 1; - // icscm_bitfield IVRIF : 1; - // icscm_bitfield HVEnable : 1;// must be cleared before passing into CAN driver - // icscm_bitfield ExtendedNetworkIndexBit : 1;//DO NOT CLOBBER THIS - // icscm_bitfield RB1 : 1; - // icscm_bitfield RTR : 1; - // icscm_bitfield EID : 6; - // } CxTRB0DLC; - // struct - // { - // icscm_bitfield len : 4; - // icscm_bitfield ExtendedNetworkIndexBit2 : 1;//DO NOT CLOBBER THIS - // icscm_bitfield UpdateSlaveOnce : 1; - // icscm_bitfield HasUpdatedSlaveOnce : 1; - // icscm_bitfield ExtendedNetworkIndexBit : 1;//DO NOT CLOBBER THIS - // icscm_bitfield BusRecovered : 1; - // icscm_bitfield SyncFerr : 1;//!< We got framing error in our sync byte. - // icscm_bitfield MidFerr : 1;//!< We got framing error in our message id. - // icscm_bitfield SlaveByteFerr : 1;//!< We got framing error in one of our slave bytes. - // icscm_bitfield TxAborted : 1;//!< This transmit was aborted. - // icscm_bitfield breakOnly : 1; - // icscm_bitfield : 2; - // } CxLIN2; - // // For use by JVPW - // struct - // { - // icscm_bitfield len : 4; - // icscm_bitfield ExtendedNetworkIndexBit2 : 1;//DO NOT CLOBBER THIS - // icscm_bitfield just_tx_timestamp : 1; - // icscm_bitfield first_seg : 1; - // icscm_bitfield ExtendedNetworkIndexBit : 1;// do not clobber ExtendedNetworkIndexBit - // icscm_bitfield D11 : 8; - // } C3xJ1850; - // // For use by the ISO/KEYWORD - // struct - // { - // icscm_bitfield len : 4; - // icscm_bitfield ExtendedNetworkIndexBit2 : 1;//DO NOT CLOBBER THIS - // icscm_bitfield FRM : 1; - // icscm_bitfield INIT : 1; - // icscm_bitfield ExtendedNetworkIndexBit : 1;// do not clobber ExtendedNetworkIndexBit - // icscm_bitfield D11 : 8; - // } C3xISO; - // struct - // { - // icscm_bitfield len : 4; - // icscm_bitfield ExtendedNetworkIndexBit2 : 1;//DO NOT CLOBBER THIS - // icscm_bitfield FRM : 1; - // icscm_bitfield : 1; - // icscm_bitfield ExtendedNetworkIndexBit : 1;// do not clobber ExtendedNetworkIndexBit - // icscm_bitfield pri : 8; - // } C3xJ1708; - // struct - // { - // uint16_t rsvd; - // } C3xETH; - // struct - // { - // uint16_t CYCLE : 6; - // uint16_t HDR_CRC_9_0 : 10; - // } C3xFlex; - // }; - // unsigned char CxTRB0Dall[8]; - // union { - // uint16_t CxTRB0STAT; - // uint16_t J1850_TX_ID; - // }; - // union { - // struct - // { - // uint32_t uiTimeStamp10uS; - // union { - // uint32_t uiTimeStamp10uSMSB; - // struct - // { - // unsigned : 28; - // unsigned res_0s : 3;// must be 0!!! - // unsigned bIsExtended : 1;// always 1 for CoreMiniMsgExtended. - // }; - // }; - // }; - // int64_t uiTimeStampLarge; - // uint8_t uiTimeStampBytes[8]; - // }; - // }; }; } diff --git a/communication/message/include/canmessage.h b/communication/message/include/canmessage.h index 2d25ca3..bfcb109 100644 --- a/communication/message/include/canmessage.h +++ b/communication/message/include/canmessage.h @@ -8,6 +8,10 @@ namespace icsneo { class CANMessage : public Message { public: uint32_t arbid; + bool isRemote = false; + bool isExtended = false; + bool isCANFD = false; + bool baudrateSwitch = false; // CAN FD only }; } diff --git a/communication/message/include/neomessage.h b/communication/message/include/neomessage.h index 0eae415..b8ea076 100644 --- a/communication/message/include/neomessage.h +++ b/communication/message/include/neomessage.h @@ -6,17 +6,105 @@ #pragma pack(push, 1) +typedef union { + struct { + uint32_t globalError : 1; + uint32_t transmitMessage : 1; + uint32_t extendedFrame : 1; + uint32_t remoteFrame : 1; + uint32_t crcError : 1; + uint32_t canErrorPassive : 1; + uint32_t incompleteFrame : 1; + uint32_t lostArbitration : 1; + uint32_t undefinedError : 1; + uint32_t canBusOff : 1; + uint32_t canErrorWarning : 1; + uint32_t canBusShortedPlus : 1; + uint32_t canBusShortedGround : 1; + uint32_t checksumError : 1; + uint32_t badMessageBitTimeError : 1; + uint32_t ifrData : 1; + uint32_t hardwareCommError : 1; + uint32_t expectedLengthError : 1; + uint32_t incomingNoMatch : 1; + uint32_t statusBreak : 1; + uint32_t avsiRecOverflow : 1; + uint32_t testTrigger : 1; + uint32_t audioComment : 1; + uint32_t gpsData : 1; + uint32_t analogDigitalInput : 1; + uint32_t textComment : 1; + uint32_t networkMessageType : 1; + uint32_t vsiTXUnderrun : 1; + uint32_t vsiIFRCRCBit : 1; + uint32_t initMessage : 1; + //uint32_t highSpeedMessage : 1; // Occupies the same space as flexraySecondStartupFrame + uint32_t flexraySecondStartupFrame : 1; + uint32_t extended : 1; + // ~~~ End of bitfield 1 ~~~ + uint32_t hasValue : 1; + uint32_t valueIsBoolean : 1; + uint32_t highVoltage : 1; + uint32_t longMessage : 1; + uint32_t : 12; + uint32_t globalChange : 1; + uint32_t errorFrame : 1; + uint32_t : 2; + uint32_t endOfLongMessage : 1; + uint32_t linErrorRXBreakNotZero : 1; + uint32_t linErrorRXBreakTooShort : 1; + uint32_t linErrorRXSyncNot55 : 1; + uint32_t linErrorRXDataGreaterEight : 1; + uint32_t linErrorTXRXMismatch : 1; + uint32_t linErrorMessageIDParity : 1; + //isoFrameError + uint32_t linSyncFrameError : 1; + //isoOverflowError + uint32_t linIDFrameError : 1; + //isoParityError + uint32_t linSlaveByteError : 1; + uint32_t rxTimeoutError : 1; + uint32_t linNoSlaveData : 1; + // mostPacketData + // mostStatus + // mostLowLevel + // mostControlData + // mostMHPUserData + // mostMHPControlData + // mostI2SDump + // mostTooShort + // most50 + // most150 + // mostChangedParameter + // ethernetCRCError + // ethernetFrameTooShort + // ethernetFCSAvailable + // ~~~ End of bitfield 2 ~~~ + //uint32_t linJustBreakSync : 1; + //uint32_t linSlaveDataTooShort : 1; + //uint32_t linOnlyUpdateSlaveTableOnce : 1; + uint32_t canfdESI : 1; + uint32_t canfdIDE : 1; + uint32_t canfdRTR : 1; + uint32_t canfdFDF : 1; + uint32_t canfdBRS : 1; + }; + uint32_t statusBitfield[4]; +} neomessage_statusbitfield_t; + typedef struct { + neomessage_statusbitfield_t status; uint64_t timestamp; const uint8_t* data; size_t length; - char header[4]; + uint8_t header[4]; uint16_t netid; uint8_t type; - char reserved[9]; + uint8_t reserved[9]; } neomessage_t; typedef struct { + neomessage_statusbitfield_t status; uint64_t timestamp; const uint8_t* data; size_t length; @@ -25,6 +113,7 @@ typedef struct { uint8_t type; char reserved[9]; } neomessage_can_t; +static_assert(sizeof(neomessage_can_t) == sizeof(neomessage_t), "All types of neomessage_t must be the same size!"); #pragma pack(pop) diff --git a/communication/message/neomessage.cpp b/communication/message/neomessage.cpp index 85830a4..830c221 100644 --- a/communication/message/neomessage.cpp +++ b/communication/message/neomessage.cpp @@ -15,9 +15,17 @@ neomessage_t icsneo::CreateNeoMessage(const Message& message) { neomsg.timestamp = message.timestamp; switch(type) { - case Network::Type::CAN: - ((neomessage_can_t*)&neomsg)->arbid = ((const CANMessage*)&message)->arbid; + case Network::Type::CAN: { + neomessage_can_t& can = *(neomessage_can_t*)&neomsg; + const CANMessage& canmsg = *(const CANMessage*)&message; + can.arbid = canmsg.arbid; + can.status.extendedFrame = canmsg.isExtended; + can.status.remoteFrame = canmsg.isRemote; + can.status.canfdRTR = canmsg.isRemote; + can.status.canfdFDF = canmsg.isCANFD; + can.status.canfdBRS = canmsg.baudrateSwitch; break; + } default: // TODO Implement others break;