/** * @file dtc.cpp * @brief Implementation of functions related to Diagnostic Trouble Codes (DTCs). * * This file contains the implementation of functions that manage the status * and registration of Diagnostic Trouble Codes in the system. * * @author Marcel Peterkau * @date 09.01.2024 */ #include "dtc.h" #include "debugger.h" DTCEntry_t DTCStorage[MAX_DTC_STORAGE]; // Function implementations... /** * @brief Maintains the status of Diagnostic Trouble Codes (DTCs) in the DTCStorage array. * Updates the status of existing DTCs or adds new ones based on their activity. * * @param DTC_no The number of the Diagnostic Trouble Code. * @param active Indicates whether the DTC is active (true) or inactive (false). * @param DebugValue Additional debugging information associated with the DTC. */ void MaintainDTC(DTCNum_t DTC_no, boolean active, uint32_t DebugValue) { // Iterate through the existing DTCs in the storage for (int i = 0; i < MAX_DTC_STORAGE; i++) { // Check if the DTC with the specified number exists if (DTCStorage[i].Number == DTC_no) { // If the DTC is active and was not active before, update its status if (active && DTCStorage[i].active != DTC_ACTIVE) { Debug_pushMessage("DTC gone active: %d, DebugVal: %d\n", DTC_no, DebugValue); DTCStorage[i].timestamp = millis(); DTCStorage[i].active = DTC_ACTIVE; DTCStorage[i].debugVal = DebugValue; } // If the DTC is not active anymore, update its status to previous if (!active && DTCStorage[i].active == DTC_ACTIVE) { Debug_pushMessage("DTC gone previous: %d\n", DTC_no); DTCStorage[i].active = DTC_PREVIOUS; } return; // DTC found and processed, exit the function } } // DTC was not found in the existing storage, but it is active, // so look for free space to store the new DTC if (active == true) { for (int i = 0; i < MAX_DTC_STORAGE; i++) { // Check for an empty slot in the storage if (DTCStorage[i].Number == DTC_LAST_DTC) { Debug_pushMessage("new DTC registered: %d, DebugVal: %d\n", DTC_no, DebugValue); DTCStorage[i].Number = DTC_no; DTCStorage[i].timestamp = millis(); DTCStorage[i].active = DTC_ACTIVE; DTCStorage[i].debugVal = DebugValue; return; // New DTC registered, exit the function } } } } /** * @brief Clears a specific Diagnostic Trouble Code (DTC) entry. * * This function clears the information related to a specific DTC entry, * setting its status to inactive and timestamp to zero. * * @param DTC_no The Diagnostic Trouble Code number to be cleared. */ void ClearDTC(DTCNum_t DTC_no) { for (int i = 0; i < MAX_DTC_STORAGE; i++) { if (DTCStorage[i].Number == DTC_no) { DTCStorage[i].Number = DTC_LAST_DTC; DTCStorage[i].active = DTC_INACTIVE; DTCStorage[i].timestamp = 0; } } } /** * @brief Clears all Diagnostic Trouble Code (DTC) entries. * * This function clears all DTC entries, setting their status to inactive and * timestamps to zero. */ void ClearAllDTC() { for (int i = 0; i < MAX_DTC_STORAGE; i++) { DTCStorage[i].Number = DTC_LAST_DTC; DTCStorage[i].active = DTC_INACTIVE; DTCStorage[i].timestamp = 0; } } /** * @brief Gets the last recorded Diagnostic Trouble Code (DTC) number. * * This function retrieves the DTC number of the last recorded DTC based on the * timestamp. Optionally, it can filter only active DTCs. * * @param only_active If true, considers only active DTCs; otherwise, considers all. * @return The DTC number of the last recorded DTC or DTC_LAST_DTC if none found. */ DTCNum_t getlastDTC(boolean only_active) { int8_t pointer = -1; uint32_t lasttimestamp = 0; for (int i = 0; i < MAX_DTC_STORAGE; i++) { if (DTCStorage[i].Number > 0 && DTCStorage[i].timestamp > lasttimestamp) { if (only_active == false || DTCStorage[i].active == DTC_ACTIVE) { pointer = i; lasttimestamp = DTCStorage[i].timestamp; } } } return pointer >= 0 ? DTCStorage[pointer].Number : DTC_LAST_DTC; } /** * @brief Gets the severity level for a specific Diagnostic Trouble Code (DTC). * * This function looks up the severity level associated with the provided DTC code * from the predefined list of DTC definitions. * * @param targetCode The DTC code for which to retrieve the severity. * @return The severity level of the specified DTC or DTC_NONE if not found. */ DTCSeverity_t getSeverityForDTC(DTCNum_t targetCode) { for (int i = 0; i < DTC_LAST_DTC; i++) { if (dtc_definitions[i].code == targetCode) { return dtc_definitions[i].severity; } } return DTC_NONE; } /** * @brief Processes Diagnostic Trouble Codes (DTCs) and updates system status accordingly. * * This function checks for the presence of active DTCs and adjusts the system status * based on the severity of the most critical DTC. If a critical DTC is detected, * the system status is set to sysStat_Error, potentially triggering a system shutdown. * * @note The function also preserves the original system status when transitioning to an error state * and restores it when all DTCs are cleared. */ void DTC_Process() { static tSystem_Status preserverSysStatusError; DTCNum_t lastDTC = getlastDTC(true); if (lastDTC < DTC_LAST_DTC) { globals.hasDTC = true; if (getSeverityForDTC(lastDTC) == DTC_CRITICAL && globals.systemStatus != sysStat_Shutdown) { if (globals.systemStatus != sysStat_Error) { preserverSysStatusError = globals.systemStatus; } globals.systemStatus = sysStat_Error; } } else { globals.hasDTC = false; if (globals.systemStatus == sysStat_Error) { globals.systemStatus = preserverSysStatusError; } } }