diff --git a/CanAutoNode/CanAutoNode.cpp b/CanAutoNode/CanAutoNode.cpp index 4113232..e33ab43 100644 --- a/CanAutoNode/CanAutoNode.cpp +++ b/CanAutoNode/CanAutoNode.cpp @@ -8,8 +8,6 @@ #include #include - - CanAutoNode::~CanAutoNode() { } @@ -44,9 +42,7 @@ bool CanAutoNode::IDRangesOverlap(IDRange a, IDRange b) { * @return Node represented by the bytes. */ CanAutoNode::Node CanAutoNode::nodeFromMsg(const uint8_t *msg) { - return MsgToData(msg); - } /* Converts a 32-bit integer into a byte sequence (big-endian). @@ -62,10 +58,7 @@ void CanAutoNode::shift32to8(uint32_t in, uint8_t *out) { * @param msgout Pointer to output buffer. Must be as long as a Node struct. */ void CanAutoNode::msgFromNode(Node node, uint8_t *msgout) { - memcpy(msgout,&node,sizeof(Node)); - - } CanAutoNode::CanAutoNode() { @@ -92,7 +85,6 @@ bool CanAutoNode::SendMessageToDaughterBoardByCANIDOffset(UniqueBoardID boardID, } } return false; - } /* Sends a message starting at a given CAN ID, regardless of which board has claimed it. @@ -132,7 +124,6 @@ bool CanAutoNode::SendMessageToAllBoardsOfTypeByLogIndex(uint8_t boardType, } } return foundOne; - } #ifdef CANAUTONODEDEBUG @@ -151,15 +142,12 @@ void CanAutoNode::PrintBoardID(CanAutoNode::UniqueBoardID id) { * @return true if successfully sent. */ bool CanAutoNode::SendHeartbeat() { - HeartbeatInfo beat; beat.senderBoardID = thisNode.uniqueID; - + beat.dir = GetDir(); uint8_t msg[sizeof(HeartbeatInfo)] = {}; memcpy(msg,&beat,sizeof(msg)); - return controller->SendByLogIndex(msg, HEARTBEAT_ID); - //return controller->SendByMsgID(msg, sizeof(msg), HEARTBEAT_ID); - + return controller->SendByMsgID(msg, sizeof (msg), HEARTBEAT_CAN_ID); } /* Sends a message to a daughter board by a log index on that daughter board. Can be called from @@ -177,7 +165,7 @@ bool CanAutoNode::SendMessageToDaughterByLogIndex(UniqueBoardID boardID, for(uint16_t i = 0; i < nodesInNetwork; i++) { const Node& thisDaughter = daughterNodes[i]; if(thisDaughter.uniqueID == boardID) { - return controller->SendByMsgID(msg, thisDaughter.logSizesInBytes[logIndex], thisDaughter.logOffsetsInCANIDs[logIndex]+thisDaughter.canIDRange.start); + return controller->SendByMsgID(msg, thisDaughter.logSizesInBytes[logIndex], thisDaughter.logOffsetsInCANIDs[logIndex]+thisDaughter.canIDRange.start+SEND_RECEIVE_ID_SPLIT_AMOUNT); } } return false; @@ -241,7 +229,6 @@ bool CanAutoNode::ReadMessageFromRXBuf(uint8_t logIndex, uint16_t logSize, uint8 memcpy(out,paddedOut,logSize); return true; } - #ifdef CANAUTONODEDEBUG //SOAR_PRINT("Buffer large enough, attempting read...\n"); #endif @@ -263,16 +250,13 @@ bool CanAutoNode::BoardExistsWithName(const char* name) { uint16_t CanAutoNode::GetNamesOfAllBoards(char(* outputArr)[MAX_NAME_STR_LEN], uint16_t outputArrayLen) { uint16_t num = 0; strncpy(outputArr[num++],thisNode.nodeName,MAX_NAME_STR_LEN); - // for(uint16_t i = 0; i < nodesInNetwork; i++) { strncpy(outputArr[num++],daughterNodes[i].nodeName,MAX_NAME_STR_LEN); if(num >= outputArrayLen) { break; } } - return num; - } uint16_t CanAutoNode::GetIDsOfAllBoards(CanAutoNode::UniqueBoardID* outputArr, uint16_t outputArrayLen) { @@ -284,9 +268,7 @@ uint16_t CanAutoNode::GetIDsOfAllBoards(CanAutoNode::UniqueBoardID* outputArr, u break; } } - return num; - } CanAutoNode::UniqueBoardID CanAutoNode::GetIDOfBoardWithName(const char* name) { @@ -314,7 +296,6 @@ uint16_t CanAutoNode::GetNumberOfLogIndicesInBoard(UniqueBoardID board) { } } return 0; - } uint16_t CanAutoNode::GetSizeOfLogIndexInBoard(UniqueBoardID board, uint16_t logindex) { diff --git a/CanAutoNode/CanAutoNode.hpp b/CanAutoNode/CanAutoNode.hpp index 0e0f2de..c055498 100644 --- a/CanAutoNode/CanAutoNode.hpp +++ b/CanAutoNode/CanAutoNode.hpp @@ -12,27 +12,40 @@ * Define this to enable debug prints across the driver. Uses SOAR_PRINT. */ //#define CANAUTONODEDEBUG +//#define PACK_NETWORKLEVEL_CAN_STRUCTS + +#ifdef CANAUTONODEDEBUG +#include "SystemDefines.hpp" +#endif #include "FDCan.h" #include #include -constexpr uint32_t MAX_NODES_IN_NETWORK = 100; -constexpr uint8_t MAX_LOG_TYPES_PER_NODE = 5; -constexpr uint8_t MAX_NAME_STR_LEN = 20; +constexpr uint32_t MAX_NODES_IN_NETWORK = 20; +constexpr uint8_t MAX_LOG_TYPES_PER_NODE = 9; +constexpr uint8_t MAX_NAME_STR_LEN = 10; constexpr uint8_t MAX_JOIN_ATTEMPTS = 8; // Max 2047 for 11-bit standard FDCAN, max 536,870,911 for extended FDCAN. // See transceiver and board capabilities before changing. constexpr uint16_t MAX_CAN_ID = 2047; // Reserved CAN IDs -constexpr uint16_t JOIN_REQUEST_ID = 0; -constexpr uint16_t ACK_ID = 1; -constexpr uint16_t UPDATE_ID = 2; -constexpr uint16_t KICK_REQUEST_ID = 3; -constexpr uint16_t HEARTBEAT_ID = 4; -constexpr uint16_t MAX_RESERVED_CAN_ID = 4; // Make sure to update if adding a new reserved ID - +constexpr uint16_t JOIN_REQUEST_CAN_ID = 0; +constexpr uint16_t ACK_CAN_ID = 1; +constexpr uint16_t UPDATE_CAN_ID = 2; +constexpr uint16_t KICK_REQUEST_CAN_ID = 4; +constexpr uint16_t HEARTBEAT_CAN_ID = 5; +constexpr uint16_t MAX_RESERVED_CAN_ID = 5; // Make sure to update if adding a new reserved ID + +constexpr uint16_t JOIN_REQUEST_RLOG_INDEX = 0; +constexpr uint16_t ACK_RLOG_INDEX = 1; +constexpr uint16_t UPDATE_RLOG_INDEX = 2; +constexpr uint16_t KICK_REQUEST_RLOG_INDEX = 3; +constexpr uint16_t HEARTBEAT_RLOG_INDEX = 4; +constexpr uint16_t MAX_RESERVED_RLOG_INDEX = 4; // Make sure to update if adding a new reserved ID + +constexpr uint16_t SEND_RECEIVE_ID_SPLIT_AMOUNT = 0; #ifdef CANAUTONODEDEBUG //#include "Task.hpp" @@ -49,7 +62,6 @@ class CanAutoNode { CanAutoNode(CanAutoNode &&other) = delete; CanAutoNode& operator=(const CanAutoNode &other) = delete; - enum updateType { CAN_UPDATE_DAUGHTER, CAN_UPDATE_LAST_DAUGHTER, @@ -70,7 +82,6 @@ class CanAutoNode { bool operator==(const UniqueBoardID&) const = default; bool operator!=(const UniqueBoardID&) const = default; - }; bool SendMessageToDaughterByLogIndex(UniqueBoardID boardID, uint8_t logIndex, const uint8_t* msg); @@ -110,6 +121,9 @@ class CanAutoNode { bool operator!=(const IDRange&) const = default; }; +#ifdef PACK_NETWORKLEVEL_CAN_STRUCTS +#pragma pack(push,1) +#endif struct Node { IDRange canIDRange; UniqueBoardID uniqueID = {0}; @@ -123,16 +137,20 @@ class CanAutoNode { char nodeName[MAX_NAME_STR_LEN]; - uint16_t startingLogIndexOnMotherboard = MAX_RESERVED_CAN_ID+1; + uint16_t startingLogIndexOnMotherboard = MAX_RESERVED_RLOG_INDEX+1; bool operator==(const Node&) const = default; bool operator!=(const Node&) const = default; - }; static_assert(sizeof(Node) <= 64, "Node entries must be at most 64 bytes large. Try reducing MAX_LOGS"); struct HeartbeatInfo { + enum DIRECTION { + INVAL, + FROM_MOTH, + TO_MOTH + } dir; UniqueBoardID senderBoardID; }; @@ -146,6 +164,10 @@ class CanAutoNode { uint8_t logSizesInBytes[MAX_LOG_TYPES_PER_NODE]; }; +#ifdef PACK_NETWORKLEVEL_CAN_STRUCTS +#pragma pack(pop) +#endif + static_assert(sizeof(JoinRequest) <= 64, "Join request entries must be at most 64 bytes large. Try reducing MAX_LOGS"); FDCanController* controller = nullptr; @@ -179,10 +201,11 @@ class CanAutoNode { bool ReadMessageFromRXBuf(uint8_t logIndex, uint16_t logSize, uint8_t* out, uint16_t outLen); + virtual HeartbeatInfo::DIRECTION GetDir() const = 0; + private: CanAutoNode(const CanAutoNode &other) = delete; - }; #endif /* AUTONODE_CANAUTONODE_HPP_ */ diff --git a/CanAutoNode/CanAutoNodeDaughter.cpp b/CanAutoNode/CanAutoNodeDaughter.cpp index 4b2673b..75ad767 100644 --- a/CanAutoNode/CanAutoNodeDaughter.cpp +++ b/CanAutoNode/CanAutoNodeDaughter.cpp @@ -2,8 +2,6 @@ #include - - /* Gets the state of this daughter board. * @return The current state. */ @@ -19,13 +17,13 @@ bool CanAutoNodeDaughter::TryRequestingJoiningNetwork() { if(GetCurrentState() != UNINITIALIZED) { return false; } - srand(GetThisBoardUniqueID().u1); + srand(GetThisBoardUniqueID().u2 ^ GetThisBoardUniqueID().u1 ^ GetThisBoardUniqueID().u0); uint16_t tries = 0; while(1) { if(!RequestToJoinNetwork()) { #ifdef CANAUTONODEDEBUG - SOAR_PRINT("Failed try %d/%d\n",tries+1,MAX_JOIN_ATTEMPTS); + SOAR_PRINT("Failed try %d/%d\n",tries+1,MAX_JOIN_ATTEMPTS); #endif HAL_Delay(rand()%500+100); tries++; @@ -36,24 +34,23 @@ bool CanAutoNodeDaughter::TryRequestingJoiningNetwork() { ChangeState(REQUESTED_FAILED_WAITING_TO_RETRY); } else { #ifdef CANAUTONODEDEBUG - SOAR_PRINT("Successfully sent request\n"); + SOAR_PRINT("Successfully sent request\n"); #endif ChangeState(REQUESTED_WAITING_FOR_RESPONSE); HAL_Delay(rand()%500+100); if(CheckForAcknowledgement()) { #ifdef CANAUTONODEDEBUG - SOAR_PRINT("Received good ACK\n"); + SOAR_PRINT("Received good ACK\n"); #endif return true; } else { #ifdef CANAUTONODEDEBUG - SOAR_PRINT("Non good ACK received\n"); + SOAR_PRINT("Non good ACK received\n"); #endif ChangeState(REQUESTED_FAILED_WAITING_TO_RETRY); } } } - } /* Send a request to join the network on the reserved join request CAN ID. @@ -61,6 +58,7 @@ bool CanAutoNodeDaughter::TryRequestingJoiningNetwork() { */ bool CanAutoNodeDaughter::RequestToJoinNetwork() { + lastDetectedJoinRequest = thisNode.uniqueID; JoinRequest request; request.uniqueID = thisNode.uniqueID; request.boardType = thisNode.boardType; @@ -79,16 +77,18 @@ bool CanAutoNodeDaughter::RequestToJoinNetwork() { uint8_t msg[sizeof(JoinRequest)]; DataToMsg(request, msg); - return controller->SendByMsgID(msg, sizeof(msg), JOIN_REQUEST_ID); + return controller->SendByMsgID(msg, sizeof(msg), JOIN_REQUEST_CAN_ID); } +// you shouldn't be deleting this anyway but at least dont leak memory CanAutoNodeDaughter::~CanAutoNodeDaughter() { - + if(controller) { + delete controller; + } } - -/* Exhausts the FIFO until any acknowledgment is received. - * return true if a good acknowledgment is found. +/* @brief Exhausts the FIFO until any acknowledgment is received. + * @return true if a good acknowledgment is found. */ bool CanAutoNodeDaughter::CheckForAcknowledgement() { if(GetCurrentState() != REQUESTED_WAITING_FOR_RESPONSE) { @@ -97,25 +97,30 @@ bool CanAutoNodeDaughter::CheckForAcknowledgement() { #endif return false; } - uint8_t msg[64] = {123}; - - while(controller->ReceiveLogIndexFromRXBuf(msg, ACK_ID)) { + uint8_t msg[64] = {0}; + while(controller->ReceiveLogIndexFromRXBuf(msg, ACK_RLOG_INDEX)) { acknowledgementStatus incomingStatus = static_cast(msg[0]); switch(incomingStatus) { case ACK_GOOD: #ifdef CANAUTONODEDEBUG - SOAR_PRINT("Good ACK!\n"); + SOAR_PRINT("Good ACK!\n"); #endif - controller->DiscardLog(KICK_REQUEST_ID); // So we don't immediately get kicked on rejoining after a daughter reset + controller->DiscardLog(KICK_REQUEST_RLOG_INDEX); // So we don't immediately get kicked on rejoining after a daughter reset ChangeState(WAITING_FOR_UPDATE); return true; case ACK_NO_ROOM: ChangeState(ERROR); #ifdef CANAUTONODEDEBUG - SOAR_PRINT("No room!\n"); + SOAR_PRINT("No room!\n"); +#endif + return false; + + case ACK_BOARD_ALREADY_EXISTS: +#ifdef CANAUTONODEDEBUG + SOAR_PRINT("Already exists somehow!\n"); #endif return false; @@ -123,57 +128,73 @@ bool CanAutoNodeDaughter::CheckForAcknowledgement() { // invalid ack ChangeState(ERROR); #ifdef CANAUTONODEDEBUG - SOAR_PRINT("Invalid ACK!\n"); + SOAR_PRINT("Invalid ACK!\n"); #endif return false; } - } #ifdef CANAUTONODEDEBUG - SOAR_PRINT("Didn't receive any ACK\n"); + SOAR_PRINT("Didn't receive any ACK\n"); #endif // not received return false; } -/* Exhausts the FIFO until an update is found, or an update is partly received and times out. - * return true if successfully received update. +/* @brief Exhausts the FIFO until an update is found, or an update is partly received and times out. + * @return true if successfully received update. */ bool CanAutoNodeDaughter::CheckForUpdate() { if(GetCurrentState() != WAITING_FOR_UPDATE) { return false; } - uint8_t msg[64] = {123}; - - while(controller->ReceiveLogIndexFromRXBuf(msg, UPDATE_ID)) { + uint8_t msg[128] = {0}; + // at this point the ack should have already been sent if it was this board joining, + // so if this hits that means another board in the network tried joining or was kicked + // if the motherboard doesnt like the new board, dont even bother + while(controller->ReceiveLogIndexFromRXBuf(msg, ACK_RLOG_INDEX)) { + acknowledgementStatus incomingStatus = static_cast(msg[0]); +#ifdef CANAUTONODEDEBUG + SOAR_PRINT("even though we waiting for an update we got an ack of %d\n",incomingStatus); +#endif + if(incomingStatus != ACK_GOOD) { + ChangeState(READY); + return true; + } + } + while(controller->ReceiveLogIndexFromRXBuf(msg, UPDATE_RLOG_INDEX)) { return ReceiveUpdate(msg); - } // not received if(HAL_GetTick() - tickLastReceivedUpdatePart > 1000) { #ifdef CANAUTONODEDEBUG SOAR_PRINT("Update timed out!\n"); #endif + if(lastDetectedJoinRequest != UniqueBoardID{0} && lastDetectedJoinRequest != thisNode.uniqueID) { +#ifdef CANAUTONODEDEBUG + SOAR_PRINT("but its ok since that join request wasnt even mine :)\n"); +#endif + ChangeState(READY); + return false; + } ChangeState(ERROR); } return false; - } -/* Exhausts the FIFO until kick, join, or heartbeat is encountered while ready. +/* @brief Exhausts the FIFO until kick, join, or heartbeat is encountered while ready. * @return true if any are found. */ bool CanAutoNodeDaughter::ProcessMessage() { if(GetCurrentState() != READY) { return false; } - uint8_t msg[64] = {}; + uint8_t msg[128] = {}; bool gotOne = false; - while(controller->ReceiveLogIndexFromRXBuf(msg, KICK_REQUEST_ID)) { + while(controller->ReceiveLogIndexFromRXBuf(msg, KICK_REQUEST_RLOG_INDEX)) { gotOne = true; UniqueBoardID kickedBoard = MsgToData(msg); @@ -193,28 +214,43 @@ bool CanAutoNodeDaughter::ProcessMessage() { ChangeState(WAITING_FOR_UPDATE); gotOne = true; } - while(controller->ReceiveLogIndexFromRXBuf(msg, JOIN_REQUEST_ID)) { - + while(controller->ReceiveLogIndexFromRXBuf(msg, JOIN_REQUEST_RLOG_INDEX)) { #ifdef CANAUTONODEDEBUG SOAR_PRINT("Saw a join request from another board\n"); #endif + lastDetectedJoinRequest = MsgToData(msg).uniqueID; ChangeState( WAITING_FOR_UPDATE); gotOne = true; } - while(controller->ReceiveLogIndexFromRXBuf(msg, HEARTBEAT_ID)) { + while(controller->ReceiveLogIndexFromRXBuf(msg, ACK_RLOG_INDEX)) { - if(MsgToData(msg) == Motherboard.uniqueID) { #ifdef CANAUTONODEDEBUG - SOAR_PRINT("Received heartbeat\n"); + SOAR_PRINT("Saw an ack, presumably for another board\n"); #endif - SendHeartbeat(); + acknowledgementStatus incomingStatus = static_cast(msg[0]); + if(incomingStatus != ACK_GOOD && GetCurrentState() == WAITING_FOR_UPDATE) { + ChangeState( READY); } + gotOne = true; } + while(controller->ReceiveLogIndexFromRXBuf(msg, HEARTBEAT_RLOG_INDEX)) { + HeartbeatInfo hi = MsgToData(msg); + if(hi.dir != hi.FROM_MOTH) { + continue; + } + +#ifdef CANAUTONODEDEBUG + SOAR_PRINT("Received heartbeat\n"); +#endif + HAL_Delay(thisNode.canIDRange.start*13 % 100); + SendHeartbeat(); + gotOne = true; + } return gotOne; } @@ -243,8 +279,6 @@ void CanAutoNodeDaughter::ChangeState(daughterState target) { thisNode.canIDRange = {0,0}; break; - - default: break; } @@ -259,8 +293,8 @@ void CanAutoNodeDaughter::ChangeState(daughterState target) { */ CanAutoNodeDaughter::CanAutoNodeDaughter(FDCAN_HandleTypeDef *fdcan, const LogInit *logs, uint16_t numLogs, uint8_t boardType, uint8_t slotNumber, const char* readableName) { - controller = new FDCanController(fdcan,nullptr,0); + controller = new FDCanController(fdcan,nullptr,0); memcpy(logsToInit,logs,numLogs*sizeof(LogInit)); this->numLogs = numLogs; callbackcontroller = controller; @@ -275,13 +309,9 @@ CanAutoNodeDaughter::CanAutoNodeDaughter(FDCAN_HandleTypeDef *fdcan, const LogIn memset(this->thisNode.nodeName,0x00,MAX_NAME_STR_LEN); } - - //controller->RegisterFilterRXFIFO(0, MAX_RESERVED_CAN_ID); - - FDCanController::LogInitStruct reservedLogs[] = {{64,JOIN_REQUEST_ID},{64,ACK_ID},{64,UPDATE_ID},{64,KICK_REQUEST_ID},{64,HEARTBEAT_ID}}; + FDCanController::LogInitStruct reservedLogs[] = {{64,JOIN_REQUEST_CAN_ID},{64,ACK_CAN_ID},{sizeof(Node)+1,UPDATE_CAN_ID},{64,KICK_REQUEST_CAN_ID},{64,HEARTBEAT_CAN_ID}}; controller->RegisterLogs(reservedLogs, sizeof(reservedLogs)/sizeof(reservedLogs[0])); - } /* Sends a message to the motherboard by the log index. @@ -294,8 +324,8 @@ bool CanAutoNodeDaughter::SendMessageToMotherboardByLogID(uint16_t logID, const if(GetCurrentState() != READY) { return false; } - //printf("sending to motherboard log index %d\n",logID); - return controller->SendByLogIndex(msg, logID+MAX_RESERVED_CAN_ID+1); + uint16_t txid = determinedLogs[logID].startingMsgID - SEND_RECEIVE_ID_SPLIT_AMOUNT; + return controller->SendByMsgID(msg, determinedLogs[logID].byteLength, txid); } /* Handle receiving part of an update, updating internal node references and changing state when ready. @@ -316,47 +346,44 @@ bool CanAutoNodeDaughter::ReceiveUpdate(const uint8_t *msg) { if(receivedNode.uniqueID != thisNode.uniqueID) { this->daughterNodes[this->nodesInNetwork++] = receivedNode; #ifdef CANAUTONODEDEBUG - SOAR_PRINT("Received update for someone else... initializedLogs: %d, numLogs: %d, according to the update numLogs: %d\n",initializedLogs,numLogs,receivedNode.numberOfLogs); + SOAR_PRINT("Received update for someone else... initializedLogs: %d, numLogs: %d, according to the update numLogs: %d\n",initializedLogs,numLogs,receivedNode.numberOfLogs); #endif } else { this->thisNode = receivedNode; #ifdef CANAUTONODEDEBUG - SOAR_PRINT("Received update for me... initializedLogs: %d, numLogs: %d, according to the update numLogs: %d\n",initializedLogs,numLogs,receivedNode.numberOfLogs); + SOAR_PRINT("Received update for me... initializedLogs: %d, numLogs: %d, according to the update numLogs: %d\n",initializedLogs,numLogs,receivedNode.numberOfLogs); #endif if(!initializedLogs) { uint16_t canid = receivedNode.canIDRange.start; for(uint16_t i = 0; i < numLogs; i++) { uint16_t requiredIDs = (logsToInit[i].sizeInBytes-1)/64+1; - determinedLogs[i] = {logsToInit[i].sizeInBytes, canid}; + determinedLogs[i] = {logsToInit[i].sizeInBytes, (uint16_t)(canid+SEND_RECEIVE_ID_SPLIT_AMOUNT)}; canid += requiredIDs; #ifdef CANAUTONODEDEBUG - SOAR_PRINT("Registering log %d at canid %d byte size %d\n",i,determinedLogs[i].startingMsgID,determinedLogs[i].byteLength); + SOAR_PRINT("Registering log %d at canid %d byte size %d\n",i,determinedLogs[i].startingMsgID,determinedLogs[i].byteLength); #endif - } controller->RegisterLogs(determinedLogs, numLogs); - initializedLogs = true; } - } #ifdef CANAUTONODEDEBUG - SOAR_PRINT("Received a daughter update part for "); - PrintBoardID(receivedNode.uniqueID); - SOAR_PRINT("\n"); + SOAR_PRINT("Received a daughter update part for "); + PrintBoardID(receivedNode.uniqueID); + SOAR_PRINT("\n"); #endif break; case CAN_UPDATE_MOTHERBOARD: this->Motherboard = receivedNode; #ifdef CANAUTONODEDEBUG - SOAR_PRINT("Received a motherboard update part for "); - PrintBoardID(receivedNode.uniqueID); - SOAR_PRINT("\n"); + SOAR_PRINT("Received a motherboard update part for "); + PrintBoardID(receivedNode.uniqueID); + SOAR_PRINT("\n"); #endif break; @@ -374,10 +401,17 @@ bool CanAutoNodeDaughter::ReadMessageByLogIndex(uint8_t logIndex, return false; } uint16_t logSize = determinedLogs[logIndex].byteLength; - return ReadMessageFromRXBuf(logIndex+MAX_RESERVED_CAN_ID+1, logSize, out, outLen); - + return ReadMessageFromRXBuf(logIndex+MAX_RESERVED_RLOG_INDEX+1, logSize, out, outLen); } uint16_t CanAutoNodeDaughter::GetSizeOfLog(uint8_t logIndex) const { return determinedLogs[logIndex].byteLength; } + +bool CanAutoNodeDaughter::ExitErrorState() { + if(GetCurrentState() != CanAutoNodeDaughter::ERROR) { + return false; + } + ChangeState(CanAutoNodeDaughter::UNINITIALIZED); + return true; +} diff --git a/CanAutoNode/CanAutoNodeDaughter.hpp b/CanAutoNode/CanAutoNodeDaughter.hpp index 3cb6b54..a49e8c8 100644 --- a/CanAutoNode/CanAutoNodeDaughter.hpp +++ b/CanAutoNode/CanAutoNodeDaughter.hpp @@ -21,8 +21,6 @@ class CanAutoNodeDaughter : public CanAutoNode { ERROR }; - //CanAutoNodeDaughter(FDCanController* contr, uint16_t msgIDsToRequestStartID, uint16_t msgIDsToRequestAmount); - CanAutoNodeDaughter(FDCAN_HandleTypeDef *fdcan, const LogInit *logs, uint16_t numLogs, uint8_t boardType, uint8_t slotNumber, const char* readableName); ~CanAutoNodeDaughter(); @@ -31,10 +29,8 @@ class CanAutoNodeDaughter : public CanAutoNode { CanAutoNodeDaughter(const CanAutoNodeDaughter &) = delete; CanAutoNodeDaughter &operator=(const CanAutoNodeDaughter &) = delete; - const daughterState GetCurrentState() const; - bool TryRequestingJoiningNetwork(); bool CheckCANCommands() override { @@ -63,12 +59,12 @@ class CanAutoNodeDaughter : public CanAutoNode { uint16_t GetSizeOfLog(uint8_t logIndex) const; -protected: + bool ExitErrorState(); +protected: void ChangeState(daughterState target); -// uint32_t uniqueBoardID = HAL_GetDEVID(); Node Motherboard = {0}; bool CheckForAcknowledgement(); bool CheckForUpdate(); @@ -81,6 +77,10 @@ class CanAutoNodeDaughter : public CanAutoNode { bool ReceiveUpdate(const uint8_t* msg); + HeartbeatInfo::DIRECTION GetDir() const override { + return HeartbeatInfo::TO_MOTH; + } + uint32_t tickLastReceivedUpdatePart = 0; LogInit logsToInit[MAX_LOG_TYPES_PER_NODE]; @@ -89,9 +89,7 @@ class CanAutoNodeDaughter : public CanAutoNode { FDCanController::LogInitStruct determinedLogs[MAX_LOG_TYPES_PER_NODE]; bool initializedLogs = false; - -// const uint8_t boardType; -// const IDRange idRange; + UniqueBoardID lastDetectedJoinRequest = {0}; }; diff --git a/CanAutoNode/CanAutoNodeMotherboard.cpp b/CanAutoNode/CanAutoNodeMotherboard.cpp index f47266c..ef217cd 100644 --- a/CanAutoNode/CanAutoNodeMotherboard.cpp +++ b/CanAutoNode/CanAutoNodeMotherboard.cpp @@ -10,8 +10,6 @@ bool CanAutoNodeMotherboard::KickNode(UniqueBoardID uniqueBoardID) { bool exists = false; uint16_t foundIndex = 0; - - for(uint16_t i = 0; i < nodesInNetwork; i++) { const Node& thisNode = daughterNodes[i]; if(thisNode.uniqueID == uniqueBoardID) { @@ -28,44 +26,39 @@ bool CanAutoNodeMotherboard::KickNode(UniqueBoardID uniqueBoardID) { SOAR_PRINT(")\nNow just forcing send kick\n"); #endif - - - - //return true; } else { - // to get rid of this node, first we will identify the MOTHERBOARD log indexes to remove ON THE MOTHERBOARD - uint8_t indicesToRemove[daughterNodes[foundIndex].numberOfLogs]; - for(uint8_t i = 0; i < daughterNodes[foundIndex].numberOfLogs; i++) { - indicesToRemove[i] = daughterNodes[foundIndex].startingLogIndexOnMotherboard+i; - } - controller->RemoveLogIndices(indicesToRemove, sizeof(indicesToRemove)/sizeof(indicesToRemove[0])); - nextFreeMotherboardLogIndex -= daughterNodes[foundIndex].numberOfLogs; - - // next, we shall update all other nodes to shift their motherboard log index offsets down to fill in the gap. - // this change will be reflected to all remaining daughters in the upcoming update - // note that this does not reassign can ids. this is fine, now that this node is gone its space in the - //can address space is freed and can be reassigned. i dont care about fragmentation, if you are connecting and kicking over 2000 nodes in a random order, there is some other problem - for(uint8_t i = 0; i < nodesInNetwork; i++) { - if(i != foundIndex && daughterNodes[i].startingLogIndexOnMotherboard > daughterNodes[foundIndex].startingLogIndexOnMotherboard) { - daughterNodes[i].startingLogIndexOnMotherboard -= daughterNodes[foundIndex].numberOfLogs; + // to get rid of this node, first we will identify the MOTHERBOARD log indexes to remove ON THE MOTHERBOARD + uint8_t indicesToRemove[daughterNodes[foundIndex].numberOfLogs]; + for(uint8_t i = 0; i < daughterNodes[foundIndex].numberOfLogs; i++) { + indicesToRemove[i] = daughterNodes[foundIndex].startingLogIndexOnMotherboard+i; + } + controller->RemoveLogIndices(indicesToRemove, sizeof(indicesToRemove)/sizeof(indicesToRemove[0])); + nextFreeMotherboardLogIndex -= daughterNodes[foundIndex].numberOfLogs; + + // next, we shall update all other nodes to shift their motherboard log index offsets down to fill in the gap. + // this change will be reflected to all remaining daughters in the upcoming update + // note that this does not reassign can ids. this is fine, now that this node is gone its space in the + //can address space is freed and can be reassigned. i dont care about fragmentation, if you are connecting and kicking over 2000 nodes in a random order, there is some other problem + for(uint8_t i = 0; i < nodesInNetwork; i++) { + if(i != foundIndex && daughterNodes[i].startingLogIndexOnMotherboard > daughterNodes[foundIndex].startingLogIndexOnMotherboard) { + daughterNodes[i].startingLogIndexOnMotherboard -= daughterNodes[foundIndex].numberOfLogs; + } } - } - - // now actually remove the kicked node - daughterNodes[foundIndex] = daughterNodes[--nodesInNetwork]; + // now actually remove the kicked node + daughterNodes[foundIndex] = daughterNodes[--nodesInNetwork]; - for(uint16_t i = 0; i < recentlyJoinedNum; i++) { - if(recentlyJoined[i]->uniqueID == uniqueBoardID) { - recentlyJoined[i] = recentlyJoined[--recentlyJoinedNum]; - break; + for(uint16_t i = 0; i < recentlyJoinedNum; i++) { + if(recentlyJoined[i]->uniqueID == uniqueBoardID) { + recentlyJoined[i] = recentlyJoined[--recentlyJoinedNum]; + break; + } } - } - heartbeatGracePeriod[foundIndex] = heartbeatGracePeriod[nodesInNetwork]; + heartbeatGracePeriod[foundIndex] = heartbeatGracePeriod[nodesInNetwork]; } - if(!controller->SendByMsgID((uint8_t*)(&uniqueBoardID), sizeof(uniqueBoardID), KICK_REQUEST_ID)) { + if(!controller->SendByMsgID((uint8_t*)(&uniqueBoardID), sizeof(uniqueBoardID), KICK_REQUEST_CAN_ID)) { #ifdef CANAUTONODEDEBUG SOAR_PRINT("Tried to kick node, but failed to send! (Attempted to kick "); PrintBoardID(uniqueBoardID); @@ -74,12 +67,11 @@ bool CanAutoNodeMotherboard::KickNode(UniqueBoardID uniqueBoardID) { return false; } #ifdef CANAUTONODEDEBUG - SOAR_PRINT("Kicked node ("); - PrintBoardID(uniqueBoardID); - SOAR_PRINT(")\n"); + SOAR_PRINT("Kicked node ("); + PrintBoardID(uniqueBoardID); + SOAR_PRINT(")\n"); #endif - return SendFullUpdate(); } @@ -114,10 +106,10 @@ bool CanAutoNodeMotherboard::KickNode(uint16_t slotNumber) { CanAutoNodeMotherboard::CanAutoNodeMotherboard(FDCAN_HandleTypeDef *fdcan) { controller = new FDCanController(fdcan,nullptr,0); callbackcontroller = controller; - //controller->RegisterFilterRXFIFO(0, MAX_RESERVED_CAN_ID); + memset(heartbeatGracePeriod,0x00,sizeof(heartbeatGracePeriod)); - FDCanController::LogInitStruct reservedLogs[] = {{64,JOIN_REQUEST_ID},{64,ACK_ID},{64,UPDATE_ID},{64,KICK_REQUEST_ID},{64,HEARTBEAT_ID}}; + FDCanController::LogInitStruct reservedLogs[] = {{64,JOIN_REQUEST_CAN_ID},{64,ACK_CAN_ID},{sizeof(Node)+1,UPDATE_CAN_ID},{64,KICK_REQUEST_CAN_ID},{64,HEARTBEAT_CAN_ID}}; controller->RegisterLogs(reservedLogs, sizeof(reservedLogs)/sizeof(reservedLogs[0])); } @@ -131,15 +123,11 @@ bool CanAutoNodeMotherboard::CheckForJoinRequest() { uint8_t msg[64] = {123}; uint32_t id = 0; - - while(controller->ReceiveLogIndexFromRXBuf(msg, JOIN_REQUEST_ID)) { - + while(controller->ReceiveLogIndexFromRXBuf(msg, JOIN_REQUEST_CAN_ID)) { return ReceiveJoinRequest(msg); - } // not received return false; - } /* Attempts to incorporate a new node into the network. Will assign the new node a @@ -150,7 +138,6 @@ bool CanAutoNodeMotherboard::CheckForJoinRequest() { */ bool CanAutoNodeMotherboard::ReceiveJoinRequest(uint8_t* msg) { - JoinRequest request = MsgToData(msg); #ifdef CANAUTONODEDEBUG SOAR_PRINT("Received a join request from "); @@ -166,13 +153,16 @@ bool CanAutoNodeMotherboard::ReceiveJoinRequest(uint8_t* msg) { if(request.uniqueID == thisAlreadyExistingNode.uniqueID) { // already have this board somehow +#ifdef CANAUTONODEDEBUG + SOAR_PRINT("But it already exists!\n"); +#endif SendAck(ACK_BOARD_ALREADY_EXISTS); + HAL_Delay(10); + KickNode(request.uniqueID); return false; } - } - // Finding smallest possible gap to fit the newly requested ID range into Node sortedNodes[nodesInNetwork]; memcpy(sortedNodes,daughterNodes,sizeof(sortedNodes)); @@ -191,6 +181,9 @@ bool CanAutoNodeMotherboard::ReceiveJoinRequest(uint8_t* msg) { for(uint16_t i = 0; i < nodesInNetwork; i++) { const Node& thisNode = sortedNodes[i]; uint16_t thisAmountOfRoom = thisNode.canIDRange.start-previousEnd; + if(thisNode.canIDRange.start < previousEnd) { + thisAmountOfRoom = 0; + } if(thisAmountOfRoom < bestAmountOfRoom && thisAmountOfRoom >= requiredTotalCANIDs) { bestAmountOfRoom = thisAmountOfRoom; @@ -208,10 +201,8 @@ bool CanAutoNodeMotherboard::ReceiveJoinRequest(uint8_t* msg) { foundRoom = true; } - if(foundRoom) { // found no issues - SendAck(ACK_GOOD); #ifdef CANAUTONODEDEBUG SOAR_PRINT("Adding new node at ID range [%d,%d)\n",bestStartingFreeCANID,bestStartingFreeCANID+requiredTotalCANIDs); #endif @@ -230,17 +221,16 @@ bool CanAutoNodeMotherboard::ReceiveJoinRequest(uint8_t* msg) { newNode.logOffsetsInCANIDs[i] = thisID - bestStartingFreeCANID; newNode.logSizesInBytes[i] = request.logSizesInBytes[i]; thisID += (request.logSizesInBytes[i]-1)/64+1; - } + newNode.startingLogIndexOnMotherboard = nextFreeMotherboardLogIndex; + nextFreeMotherboardLogIndex += request.numberOfLogs; daughterNodes[nodesInNetwork] = newNode; recentlyJoined[recentlyJoinedNum++] = &daughterNodes[nodesInNetwork]; controller->RegisterLogs(newLogs, request.numberOfLogs); - heartbeatGracePeriod[nodesInNetwork] = 0; + heartbeatGracePeriod[nodesInNetwork] = 3; nodesInNetwork++; - newNode.startingLogIndexOnMotherboard = nextFreeMotherboardLogIndex; - nextFreeMotherboardLogIndex += request.numberOfLogs; - + SendAck(ACK_GOOD); HAL_Delay(50); return SendFullUpdate(); } else { @@ -250,7 +240,6 @@ bool CanAutoNodeMotherboard::ReceiveJoinRequest(uint8_t* msg) { #endif return false; } - } /* Sends an acknowledgment to the network. @@ -258,13 +247,10 @@ bool CanAutoNodeMotherboard::ReceiveJoinRequest(uint8_t* msg) { * @return true if successfully sent. */ bool CanAutoNodeMotherboard::SendAck(acknowledgementStatus status) { - uint8_t msg[] = {static_cast(status)}; - return controller->SendByMsgID(msg, sizeof(msg), ACK_ID); - + return controller->SendByMsgID(msg, sizeof(msg), ACK_CAN_ID); } - /* Sends a full list of all nodes in the network to all nodes. Serves to keep * daughter nodes up-to-date with the network contents. * Sends in multiple frames, where each frame contains one node preceded by a status byte, @@ -278,9 +264,9 @@ bool CanAutoNodeMotherboard::SendFullUpdate() { msgFromNode(thisNode, msg+1); msg[0] = CAN_UPDATE_MOTHERBOARD; - if(!controller->SendByMsgID(msg, sizeof(msg), UPDATE_ID)) { + if(!controller->SendByMsgID(msg, sizeof(msg), UPDATE_CAN_ID)) { #ifdef CANAUTONODEDEBUG - SOAR_PRINT("Failed to send motherboard update frame!\n"); + SOAR_PRINT("Failed to send motherboard update frame!\n"); #endif return false; } @@ -288,22 +274,23 @@ bool CanAutoNodeMotherboard::SendFullUpdate() { SOAR_PRINT("Sent motherboard update frame\n"); #endif + HAL_Delay(50); for(uint16_t i = 0; i < nodesInNetwork; i++) { msgFromNode(daughterNodes[i], msg+1); msg[0] = (i == nodesInNetwork-1) ? CAN_UPDATE_LAST_DAUGHTER : CAN_UPDATE_DAUGHTER; - if(!controller->SendByMsgID(msg, sizeof(msg), UPDATE_ID)) { + if(!controller->SendByMsgID(msg, sizeof(msg), UPDATE_CAN_ID)) { #ifdef CANAUTONODEDEBUG - SOAR_PRINT("Tried but failed to send daughter update frame!\n"); + SOAR_PRINT("Tried but failed to send daughter update frame!\n"); #endif return false; } + HAL_Delay(50); #ifdef CANAUTONODEDEBUG SOAR_PRINT("Sent daughter update frame %d/%d\n",i+1,nodesInNetwork); #endif } return true; - } /* Sends a heartbeat, then monitors for responses. Will wait up to one second. @@ -314,73 +301,73 @@ bool CanAutoNodeMotherboard::Heartbeat() { this->lastHeartbeatTick = HAL_GetTick(); + if(nodesInNetwork == 0) { // there's nobody here, just don't + return true; + } + if(!SendHeartbeat()) { return false; } - - - bool received[nodesInNetwork]; + uint8_t received[nodesInNetwork]; memset(received,0,sizeof(received)); - for(uint16_t i = 0; i < 1000; i++) { - HAL_Delay(1); + uint32_t last = HAL_GetTick(); + uint16_t i = 0; + while(HAL_GetTick()-last < 1000){ + i++; uint8_t out[64]; - uint32_t id = 0; - if(controller->ReceiveLogIndexFromRXBuf(out, HEARTBEAT_ID)) { + if(controller->ReceiveLogIndexFromRXBuf(out, HEARTBEAT_RLOG_INDEX)) { - UniqueBoardID responseID = MsgToData(out); - bool foundResponder = false; + HeartbeatInfo hi = MsgToData(out); + UniqueBoardID responseID = hi.senderBoardID; + bool foundResponder = false; #ifdef CANAUTONODEDEBUG - SOAR_PRINT("Got a heartbeat from "); - PrintBoardID(responseID); - SOAR_PRINT(", there are %d daughter nodes in the network\n",nodesInNetwork); + SOAR_PRINT("Got a heartbeat from "); + PrintBoardID(responseID); + SOAR_PRINT(", there are %d daughter nodes in the network\n",nodesInNetwork); #endif - for(int node = 0; node < nodesInNetwork; node++) { - if(daughterNodes[node].uniqueID == responseID) { - if(received[node]) { - // received multiple heartbeats from the same node? + for(int node = 0; node < nodesInNetwork; node++) { + if(daughterNodes[node].uniqueID == responseID) { + if(received[node]++ > 2) { + // received 3 or more heartbeats from the same node? #ifdef CANAUTONODEDEBUG - SOAR_PRINT("Received multiple heartbeats from "); - PrintBoardID(responseID); - SOAR_PRINT(", kicking\n"); + SOAR_PRINT("Received multiple heartbeats from "); + PrintBoardID(responseID); + SOAR_PRINT(", kicking\n"); #endif - KickNode(responseID); - } + KickNode(responseID); + } #ifdef CANAUTONODEDEBUG - SOAR_PRINT("Found the source of this heartbeat at %d!\n",node); + SOAR_PRINT("Found the source of this heartbeat at %d!\n",node); #endif - received[node] = true; - foundResponder = true; - break; - } + + foundResponder = true; + break; } - bool gotAllOfThem = true; - for(uint8_t j = 0; j < nodesInNetwork; j++) { - if(!received[j]) { - gotAllOfThem = false; - break; - } + } + bool gotAllOfThem = true; + for(uint8_t j = 0; j < nodesInNetwork; j++) { + if(!received[j]) { + gotAllOfThem = false; + break; } + } - if(!foundResponder) { - // ??? a node that wasn't in the network just responded to the heartbeat? get out + if(!foundResponder) { + // ??? a node that wasn't in the network just responded to the heartbeat? get out #ifdef CANAUTONODEDEBUG - SOAR_PRINT("Received heartbeat from unrecognized node "); - PrintBoardID(responseID); - SOAR_PRINT(", kicking\n"); + SOAR_PRINT("Received heartbeat from unrecognized node "); + PrintBoardID(responseID); + SOAR_PRINT(", kicking\n"); #endif - KickNode(responseID); - } - - - if(gotAllOfThem) { - return true; // just leave early, we got all the responses - } - - + KickNode(responseID); + } + if(gotAllOfThem) { + return true; // just leave early, we got all the responses + } } if(i > 10 && nodesInNetwork == 0) { @@ -391,28 +378,34 @@ bool CanAutoNodeMotherboard::Heartbeat() { for(size_t i = 0; i < nodesInNetwork; i++) { if(!received[i]) { // Found a node that never responded to the heartbeat #ifdef CANAUTONODEDEBUG - SOAR_PRINT("Received no heartbeat from "); - PrintBoardID(daughterNodes[i].uniqueID); - SOAR_PRINT(", kicking\n"); + SOAR_PRINT("Received no heartbeat from "); + PrintBoardID(daughterNodes[i].uniqueID); + if(heartbeatGracePeriod[i] > 0) { + SOAR_PRINT(", but it had grace!\n"); + } else { + SOAR_PRINT(", kicking\n"); + } #endif - if(heartbeatGracePeriod[i] > 0) { - heartbeatGracePeriod[i]--; - } else { - KickNode(daughterNodes[i].uniqueID); - } + if(heartbeatGracePeriod[i] > 0) { + heartbeatGracePeriod[i]--; + } else { + KickNode(daughterNodes[i].uniqueID); + } } } return true; - } +/* @brief Gets the nuumber of ticks since the last time a heartbeat was sent. + * @return Ticks + */ uint32_t CanAutoNodeMotherboard::GetTicksSinceLastHeartbeat() const { return HAL_GetTick() - lastHeartbeatTick; } -/* - * Reads an incoming message from a daughter node on a given log index. +/* @brief Reads an incoming message from a daughter node on a given log index. + * @return true on success. */ bool CanAutoNodeMotherboard::ReadMessageFromDaughterByLogIndex( UniqueBoardID daughter, uint8_t logIndex, uint8_t *out, @@ -422,27 +415,23 @@ bool CanAutoNodeMotherboard::ReadMessageFromDaughterByLogIndex( const Node& thisNode = daughterNodes[i]; if(thisNode.uniqueID == daughter) { - if(logIndex >= thisNode.numberOfLogs) { + if(logIndex >= thisNode.numberOfLogs) { #ifdef CANAUTONODEDEBUG - SOAR_PRINT("Cannot read log index %d from daughter with max index %d",logIndex,thisNode.numberOfLogs); + SOAR_PRINT("Cannot read log index %d from daughter with max index %d",logIndex,thisNode.numberOfLogs); #endif - return false; - } + return false; + } return ReadMessageFromRXBuf(thisNode.startingLogIndexOnMotherboard+logIndex, thisNode.logSizesInBytes[logIndex], out, outSize); } } -#ifdef CANAUTONODEDEBUG - SOAR_PRINT("No node with that ID!\n"); -#endif - return false; + return false; } /* Returns an array of name strings of any boards that joined the network since the last call of this function. * @param outputArr A pointer to an array of char arrays to store the names. * @param outputBufferLen For safety, will not write more entries than this to the output. * @return The number of nodes returned in the array. - * */ uint16_t CanAutoNodeMotherboard::GetNamesOfNewlyJoinedBoards(char(*outputArr)[MAX_NAME_STR_LEN], uint16_t outputBufferLen) { @@ -456,9 +445,15 @@ uint16_t CanAutoNodeMotherboard::GetNamesOfNewlyJoinedBoards(char(*outputArr)[MA if(i >= outputBufferLen) { break; } - } memcpy(recentlyJoined,&recentlyJoined[recentlyJoinedNum-num],(num)*sizeof(Node*)); recentlyJoinedNum -= num; + return num; + +} +CanAutoNodeMotherboard::~CanAutoNodeMotherboard() { + if(controller) { + delete controller; + } } diff --git a/CanAutoNode/CanAutoNodeMotherboard.hpp b/CanAutoNode/CanAutoNodeMotherboard.hpp index 576a6eb..0a8bcb4 100644 --- a/CanAutoNode/CanAutoNodeMotherboard.hpp +++ b/CanAutoNode/CanAutoNodeMotherboard.hpp @@ -8,9 +8,11 @@ class CanAutoNodeMotherboard : public CanAutoNode { public: - CanAutoNodeMotherboard(FDCAN_HandleTypeDef *fdcan); + ~CanAutoNodeMotherboard(); + CanAutoNodeMotherboard() = delete; + bool CheckCANCommands() override { return CheckForJoinRequest(); } @@ -42,9 +44,13 @@ class CanAutoNodeMotherboard : public CanAutoNode { bool CheckForJoinRequest(); + HeartbeatInfo::DIRECTION GetDir() const override { + return HeartbeatInfo::FROM_MOTH; + } + uint32_t lastHeartbeatTick = 0; - uint16_t nextFreeMotherboardLogIndex = 0; + uint16_t nextFreeMotherboardLogIndex = MAX_RESERVED_RLOG_INDEX+1; Node* recentlyJoined[MAX_NODES_IN_NETWORK]; uint16_t recentlyJoinedNum = 0; diff --git a/CanAutoNode/LogTypes/DAQLogs.hpp b/CanAutoNode/LogTypes/DAQLogs.hpp index c323fbf..5c3ea97 100644 --- a/CanAutoNode/LogTypes/DAQLogs.hpp +++ b/CanAutoNode/LogTypes/DAQLogs.hpp @@ -11,11 +11,19 @@ #include "LogStructs.hpp" #include "CanAutoNodeDaughter.hpp" +#ifdef PACK_CAN_STRUCTS +#pragma pack(push,1) +#endif // Custom Data Types struct DAQ_AIR_BRAKES_COMMAND { bool airBrakesGo; }; + +#ifdef PACK_CAN_STRUCTS +#pragma pack(pop) +#endif + // Add CAN logs here in the order you want them #define DAQ_LOGS_X \ X(CanImuData6Axis) \ diff --git a/CanAutoNode/LogTypes/LogStructs.hpp b/CanAutoNode/LogTypes/LogStructs.hpp index db0d134..a45d061 100644 --- a/CanAutoNode/LogTypes/LogStructs.hpp +++ b/CanAutoNode/LogTypes/LogStructs.hpp @@ -8,6 +8,11 @@ #ifndef LOGSTRUCTS_HPP_ #define LOGSTRUCTS_HPP_ +//#define PACK_CAN_STRUCTS + +#ifdef PACK_CAN_STRUCTS +#pragma pack(push,1) +#endif // Possible IMU structs struct CanImuData9Axis { uint32_t accel_x; @@ -47,5 +52,8 @@ struct CanMagData { uint32_t mag_y; uint32_t mag_z; }; +#ifdef PACK_CAN_STRUCTS +#pragma pack(pop) +#endif #endif /* LOGSTRUCTS_HPP_ */ diff --git a/CanAutoNode/LogTypes/RPBLogs.hpp b/CanAutoNode/LogTypes/RPBLogs.hpp index 2963fe8..927eee2 100644 --- a/CanAutoNode/LogTypes/RPBLogs.hpp +++ b/CanAutoNode/LogTypes/RPBLogs.hpp @@ -11,7 +11,9 @@ #include "LogStructs.hpp" #include "CanAutoNodeDaughter.hpp" - +#ifdef PACK_CAN_STRUCTS +#pragma pack(push,1) +#endif // Custom Data Types struct RPB_CAMERA_POWER_COMMAND { uint8_t camera; @@ -35,6 +37,9 @@ struct RPB_FROM_DAQ_AIR_BRAKES_LEVEL { uint8_t level; }; +#ifdef PACK_CAN_STRUCTS +#pragma pack(pop) +#endif // Add CAN logs here in the order you want them #define RPB_CAN_LOGS \ X(RPB_CAMERA_POWER_COMMAND) \ diff --git a/CanAutoNode/LogTypes/SOLLogs.hpp b/CanAutoNode/LogTypes/SOLLogs.hpp new file mode 100644 index 0000000..5f1d31c --- /dev/null +++ b/CanAutoNode/LogTypes/SOLLogs.hpp @@ -0,0 +1,49 @@ +/* + * CanStructs.hpp + * + * Created on: May 2, 2026 + * Author: Local user + */ + +#ifndef SOLLOGS_HPP_ +#define SOLLOGS_HPP_ + +#include "LogStructs.hpp" +#include "CanAutoNodeDaughter.hpp" + +#ifdef PACK_CAN_STRUCTS +#pragma pack(push,1) +#endif +// Custom Data Types +struct SOL_POWER_COMMAND { + enum SOLENOID { + SOL_30W_A, + SOL_30W_B, + SOL_30W_C, + SOL_30W_D, + SOL_15W_A, + SOL_15W_B, + + } sol; + bool powerOn; +}; + +#ifdef PACK_CAN_STRUCTS +#pragma pack(pop) +#endif + +// Add CAN logs here in the order you want them +#define SOL_CAN_LOGS \ + X(SOL_POWER_COMMAND) + +#define X(x) sizeof(x), +const CanAutoNodeDaughter::LogInit SOL_Init[] = {SOL_CAN_LOGS}; +#undef X + +#define X(x) _ ## x ## _LOGINDEX, +enum SOL_LogIndexes {SOL_CAN_LOGS SOL_COUNT} ; +#undef X + + +#undef struct +#endif /* SOLLOGS_HPP_ */