diff --git a/Software/include/can.h b/Software/include/can.h index 6de4206..9b4dd3a 100644 --- a/Software/include/can.h +++ b/Software/include/can.h @@ -1,3 +1,16 @@ +/** + * @file can.h + * + * @brief Header file for Controller Area Network (CAN) functionality in the ChainLube application. + * + * This file provides functions and structures related to Controller Area Network (CAN) + * communication for the ChainLube project. It includes functions for initializing CAN, + * processing CAN messages, and retrieving wheel speed from CAN data. + * + * @author Marcel Peterkau + * @date 09.01.2024 + */ + #ifndef _CAN_H_ #define _CAN_H_ @@ -9,6 +22,7 @@ #include "dtc.h" #include "debugger.h" +// CAN frame structure definition struct can_frame { unsigned long can_id; @@ -16,8 +30,9 @@ struct can_frame uint8_t data[8] __attribute__((aligned(8))); }; +// Function prototypes void Init_CAN(); void CAN_Process(); uint32_t Process_CAN_WheelSpeed(); -#endif \ No newline at end of file +#endif diff --git a/Software/include/common.h b/Software/include/common.h index 4d25a13..864e8d0 100644 --- a/Software/include/common.h +++ b/Software/include/common.h @@ -1,3 +1,16 @@ +/** + * @file common.h + * + * @brief Header file for common definitions and macros in the ChainLube application. + * + * This file defines common macros, GPIO configurations, and other shared constants + * for the ChainLube project. It includes definitions for GPIO pins, OTA delays, pulse lengths, + * and other common settings used across the project. + * + * @author Marcel Peterkau + * @date 09.01.2024 + */ + #ifndef _COMMON_H_ #define _COMMON_H_ @@ -5,6 +18,7 @@ #define QUOTE(x) Q(x) #define SET_BIT(value, bitPosition) ((value) |= (1U << (bitPosition))) +// Conditional compilation based on PCB revision #if PCB_REV == 1 #define GPIO_BUTTON D7 #define GPIO_LED D8 @@ -40,17 +54,17 @@ #define LUBE_PULSE_LENGHT_MS 160 #define LUBE_PULSE_PAUSE_MS 340 +// Pump pulse parameters // -> 2Hz PumpPulse -// -> 49,7cc / h @ 2Hz -// -> 49,7 ml / h @ 2Hz -// -> 828,4µl / min @ 2Hz -// -> 828,3µl / 60s -// -> 13,81µl / 1s -// -> 6,90µl / Pulse - +// -> 49.7cc / h @ 2Hz +// -> 49.7 ml / h @ 2Hz +// -> 828.4µl / min @ 2Hz +// -> 828.3µl / 60s +// -> 13.81µl / 1s +// -> 6.90µl / Pulse #define DEFAULT_PUMP_DOSE 7 #define STARTUP_DELAY 5000 #define SHUTDOWN_DELAY_MS 5000 -#endif \ No newline at end of file +#endif diff --git a/Software/include/config.h b/Software/include/config.h index b19348a..cd5360c 100644 --- a/Software/include/config.h +++ b/Software/include/config.h @@ -1,3 +1,17 @@ +/** + * @file config.h + * + * @brief Header file for configuration settings and EEPROM operations in the ChainLube application. + * + * This file defines configuration settings for the ChainLube project, including default values, + * EEPROM structures, and functions for EEPROM operations. It also defines enums for different sources + * of speed input, GPS baud rates, and CAN bus sources. Additionally, it includes functions for EEPROM handling + * such as storing, retrieving, and formatting configuration data. + * + * @author Marcel Peterkau + * @date 09.01.2024 + */ + #ifndef _CONFIG_H_ #define _CONFIG_H_ @@ -14,6 +28,7 @@ #define EEPROM_SIZE_BYTES I2C_DEVICESIZE_24LC256 #endif +// Enum for different sources of speed input typedef enum SpeedSource_e { #ifdef FEATURE_ENABLE_TIMER @@ -24,6 +39,7 @@ typedef enum SpeedSource_e SOURCE_CAN } SpeedSource_t; +// String representation of SpeedSource enum const char SpeedSourceString[][8] = { #ifdef FEATURE_ENABLE_TIMER "Timer", @@ -33,32 +49,37 @@ const char SpeedSourceString[][8] = { "CAN-Bus" }; +const size_t SpeedSourceString_Elements = sizeof(SpeedSourceString) / sizeof(SpeedSourceString[0]); + +// Enum for GPS baud rates typedef enum GPSBaudRate_e { BAUD_9600, BAUD_115200 } GPSBaudRate_t; +// String representation of GPSBaudRate enum const char GPSBaudRateString[][7] = { "9600", "115200"}; const size_t GPSBaudRateString_Elements = sizeof(GPSBaudRateString) / sizeof(GPSBaudRateString[0]); +// Enum for CAN bus sources typedef enum CANSource_e { KTM_890_ADV_R_2021, KTM_1290_SD_R_2023 } CANSource_t; +// String representation of CANSource enum const char CANSourceString[][30] = { "KTM 890 Adventure R (2021)", "KTM 1290 Superduke R (2023)"}; const size_t CANSourceString_Elements = sizeof(CANSourceString) / sizeof(CANSourceString[0]); -const size_t SpeedSourceString_Elements = sizeof(SpeedSourceString) / sizeof(SpeedSourceString[0]); - +// Structure for persistence data stored in EEPROM typedef struct { uint16_t writeCycleCounter = 0; @@ -69,6 +90,7 @@ typedef struct uint32_t checksum = 0; } persistenceData_t; +// Structure for configuration settings stored in EEPROM typedef struct { uint8_t EEPROM_Version = 0; @@ -92,6 +114,7 @@ typedef struct uint32_t checksum = 0; } LubeConfig_t; +// Default configuration settings const LubeConfig_t LubeConfig_defaults = { 0, 8000, 4000, 320, DEFAULT_PUMP_DOSE, 30, 1, 150, 70, 18, 2000, 25, SOURCE_IMPULSE, BAUD_115200, @@ -117,4 +140,4 @@ uint32_t ConfigSanityCheck(bool autocorrect = false); extern LubeConfig_t LubeConfig; extern persistenceData_t PersistenceData; extern uint16_t eePersistenceMarker; -#endif // _CONFIG_H_ \ No newline at end of file +#endif // _CONFIG_H_ diff --git a/Software/include/debugger.h b/Software/include/debugger.h index 0fbe6ab..a81a9b6 100644 --- a/Software/include/debugger.h +++ b/Software/include/debugger.h @@ -1,9 +1,21 @@ +/** + * @file debugger.h + * + * @brief Header file for debugging functions and status in the ChainLube application. + * + * This file declares functions and status definitions for debugging purposes in the ChainLube project. + * It includes functions to print system information, WiFi information, format EEPROM data, + * handle debug messages, and manage the status of different debug ports. + * + * @author Marcel Peterkau + * @date 09.01.2024 + */ + #ifndef _DEBUGGER_H_ #define _DEBUGGER_H_ #include #include "webui.h" - const char PROGMEM helpCmd[] = "sysinfo - System Info\n" "netinfo - WiFi Info\n" "formatPDS - Format Persistence EEPROM Data\n" diff --git a/Software/include/dtc.h b/Software/include/dtc.h index 5090e19..5e23ba8 100644 --- a/Software/include/dtc.h +++ b/Software/include/dtc.h @@ -1,3 +1,16 @@ +/** + * @file dtc.h + * + * @brief Header file for handling Diagnostic Trouble Codes (DTC) in the ChainLube application. + * + * This file provides definitions and functions for handling Diagnostic Trouble Codes (DTC) + * in the ChainLube project. It includes structures for DTC entries, severity levels, + * and functions for DTC maintenance and processing. DTCs are used to track system errors and issues. + * + * @author Marcel Peterkau + * @date 09.01.2024 + */ + #ifndef _DTC_H_ #define _DTC_H_ diff --git a/Software/include/dtc_defs.h b/Software/include/dtc_defs.h index 297cd5c..aeb9da4 100644 --- a/Software/include/dtc_defs.h +++ b/Software/include/dtc_defs.h @@ -1,4 +1,18 @@ -// Auto-generated by script on 2023-12-04 02:10:49 +/** + * @file dtc_defs.h + * + * @brief Header file for Diagnostic Trouble Code (DTC) definitions in the ChainLube application. + * + * This file contains definitions for Diagnostic Trouble Codes (DTC) in the ChainLube project. + * It includes enums for DTC active status, severity levels, and specific DTC codes. + * The file also defines an array of DTC definitions and a timestamp indicating the generation time. + * + * @note This file is auto-generated by a script on 2024-01-09 12:08:43. + * + * @author Marcel Peterkau + * @date 09.01.2024 + */ + #ifndef DTC_DEFS_H #define DTC_DEFS_H @@ -66,6 +80,6 @@ const DTC_t dtc_definitions[] = { { DTC_LAST_DTC , DTC_NONE } // Last Error }; -const uint32_t dtc_generation_timestamp = 1701652249; +const uint32_t dtc_generation_timestamp = 1704798523; #endif // DTC_DEFS_H \ No newline at end of file diff --git a/Software/include/dtc_defs.h.j2 b/Software/include/dtc_defs.h.j2 index 88c6e1d..2aa148e 100644 --- a/Software/include/dtc_defs.h.j2 +++ b/Software/include/dtc_defs.h.j2 @@ -1,4 +1,18 @@ -// Auto-generated by script on {{ timestamp }} +/** + * @file dtc_defs.h + * + * @brief Header file for Diagnostic Trouble Code (DTC) definitions in the ChainLube application. + * + * This file contains definitions for Diagnostic Trouble Codes (DTC) in the ChainLube project. + * It includes enums for DTC active status, severity levels, and specific DTC codes. + * The file also defines an array of DTC definitions and a timestamp indicating the generation time. + * + * @note This file is auto-generated by a script on {{ timestamp }}. + * + * @author Marcel Peterkau + * @date 09.01.2024 + */ + #ifndef DTC_DEFS_H #define DTC_DEFS_H diff --git a/Software/include/globals.h b/Software/include/globals.h index 69b29fe..9bd5681 100644 --- a/Software/include/globals.h +++ b/Software/include/globals.h @@ -1,3 +1,16 @@ +/** + * @file globals.h + * + * @brief Header file for global variables and enums in the ChainLube application. + * + * This file contains declarations for global variables and enums used in the ChainLube application. + * It includes enums for system status and EEPROM-related requests, as well as a struct for global variables. + * The file also defines a struct for constants and initializes it with firmware and required flash version information. + * + * @author Marcel Peterkau + * @date 09.01.2024 + */ + #ifndef _GLOBALS_H_ #define _GLOBALS_H_ @@ -29,29 +42,29 @@ typedef enum eEERequest typedef struct Globals_s { - tSystem_Status systemStatus = sysStat_Startup; - tSystem_Status resumeStatus = sysStat_Startup; - char systemStatustxt[16] = ""; - uint16_t purgePulses = 0; - eEERequest requestEEAction = EE_IDLE; - char DeviceName[33]; - char FlashVersion[10]; - uint16_t eePersistanceAdress; - uint8_t TankPercentage; - bool hasDTC; - bool measurementActive; - uint32_t measuredPulses; + tSystem_Status systemStatus = sysStat_Startup; /**< Current system status */ + tSystem_Status resumeStatus = sysStat_Startup; /**< Status to resume after rain mode */ + char systemStatustxt[16] = ""; /**< Text representation of system status */ + uint16_t purgePulses = 0; /**< Number of purge pulses */ + eEERequest requestEEAction = EE_IDLE;; /**< EEPROM-related request */ + char DeviceName[33]; /**< Device name */ + char FlashVersion[10]; /**< Flash version */ + uint16_t eePersistanceAdress; /**< EEPROM persistence address */ + uint8_t TankPercentage; /**< Tank percentage */ + bool hasDTC; /**< Flag indicating the presence of Diagnostic Trouble Codes (DTC) */ + bool measurementActive; /**< Flag indicating active measurement */ + uint32_t measuredPulses; /**< Number of measured pulses */ } Globals_t; -extern Globals_t globals; +extern Globals_t globals; /**< Global variable struct */ typedef struct Constants_s { - uint8_t FW_Version_major; - uint8_t FW_Version_minor; - uint8_t Required_Flash_Version_major; - uint8_t Required_Flash_Version_minor; - char GitHash[11]; + uint8_t FW_Version_major; /**< Firmware version major number */ + uint8_t FW_Version_minor; /**< Firmware version minor number */ + uint8_t Required_Flash_Version_major; /**< Required flash version major number */ + uint8_t Required_Flash_Version_minor; /**< Required flash version minor number */ + char GitHash[11]; /**< Git hash string */ } Constants_t; const Constants_t constants PROGMEM = { @@ -60,6 +73,9 @@ const Constants_t constants PROGMEM = { GIT_REV // Git-Hash-String }; +/** + * @brief Initializes global variables. + */ void initGlobals(); -#endif \ No newline at end of file +#endif // _GLOBALS_H_ diff --git a/Software/include/gps.h b/Software/include/gps.h index a3b66b0..03ae377 100644 --- a/Software/include/gps.h +++ b/Software/include/gps.h @@ -1,3 +1,17 @@ +/** + * @file gps.h + * + * @brief Header file for GPS-related functions in the ChainLube application. + * + * This file contains declarations for functions related to GPS (Global Positioning System) functionality + * within the ChainLube application. It includes the initialization of the GPS module and processing of GPS + * data to calculate wheel speed. Additionally, it references other necessary header files for configuration, + * common definitions, diagnostics, and debugging. + * + * @author Marcel Peterkau + * @date 09.01.2024 + */ + #ifndef _GPS_H_ #define _GPS_H_ @@ -7,7 +21,16 @@ #include "dtc.h" #include "debugger.h" +/** + * @brief Initializes the GPS module. + */ void Init_GPS(); + +/** + * @brief Processes GPS data to calculate wheel speed. + * + * @return Calculated wheel speed in millimeters per second. + */ uint32_t Process_GPS_WheelSpeed(); -#endif \ No newline at end of file +#endif // _GPS_H_ diff --git a/Software/include/led_colors.h b/Software/include/led_colors.h index 2454d98..0211f9e 100644 --- a/Software/include/led_colors.h +++ b/Software/include/led_colors.h @@ -1,3 +1,16 @@ +/** + * @file led_colors.h + * + * @brief Header file defining color values for LEDs in the ChainLube application. + * + * This file contains color definitions in hexadecimal format for various states and events of LEDs + * used in the ChainLube application. It provides a convenient way to reference specific colors for + * different visual indications in the system. + * + * @author Marcel Peterkau + * @date 09.01.2024 + */ + #ifndef _LED_COLORS_H_ #define _LED_COLORS_H_ @@ -19,17 +32,14 @@ #define COLOR_AMBER 0xFF6400 #define COLOR_WARM_WHITE 0xFDF5E6 - #define LED_DEFAULT_COLOR COLOR_WARM_WHITE #define LED_STARTUP_NORMAL COLOR_WARM_WHITE #define LED_STARTUP_TANKWARN COLOR_AMBER -#define LED_NORMAL_COLOR COLOR_GREEN -#define LED_RAIN_COLOR COLOR_BLUE +#define LED_NORMAL_COLOR COLOR_GREEN +#define LED_RAIN_COLOR COLOR_BLUE #define LED_WIFI_BLINK COLOR_YELLOW #define LED_PURGE_COLOR COLOR_MAGENTA #define LED_ERROR_BLINK COLOR_RED #define LED_SHUTDOWN_BLINK COLOR_CYAN - - #endif /* _LED_COLORS_H_ */ diff --git a/Software/include/lubeapp.h b/Software/include/lubeapp.h index 5c55f75..98e8bfe 100644 --- a/Software/include/lubeapp.h +++ b/Software/include/lubeapp.h @@ -1,3 +1,15 @@ +/** + * @file lubeapp.h + * + * @brief Header file for the ChainLube application functions. + * + * This file contains function declarations related to the main functionality of the ChainLube + * application. It includes functions for running the application and generating lubrication pulses. + * + * @author Marcel Peterkau + * @date 09.01.2024 + */ + #ifndef _LUBEAPP_H_ #define _LUBEAPP_H_ @@ -12,4 +24,4 @@ void RunLubeApp(uint32_t add_milimeters); void LubePulse(); -#endif \ No newline at end of file +#endif /* _LUBEAPP_H_ */ diff --git a/Software/include/sanitycheck.h b/Software/include/sanitycheck.h index 6da5368..777a386 100644 --- a/Software/include/sanitycheck.h +++ b/Software/include/sanitycheck.h @@ -1,3 +1,15 @@ +/** + * @file sanitycheck.h + * + * @brief Header file for sanity checks and configuration validation in the ChainLube application. + * + * This file contains checks and validations to ensure that the configuration and features of the + * ChainLube application are compatible with the selected PCB revision and defined parameters. + * + * @author Marcel Peterkau + * @date 09.01.2024 + */ + #ifndef _SANITYCHECK_H_ #define _SANITYCHECK_H_ @@ -34,4 +46,4 @@ #error "You must define an WIFI_AP_PASSWORD for Standalone AP-Mode" #endif -#endif //_SANITYCHECK_H_ \ No newline at end of file +#endif // _SANITYCHECK_H_ diff --git a/Software/include/webui.h b/Software/include/webui.h index e708b91..badb114 100644 --- a/Software/include/webui.h +++ b/Software/include/webui.h @@ -1,3 +1,16 @@ +/** + * @file webui.h + * + * @brief Header file for the web-based user interface (WebUI) in the ChainLube application. + * + * This file contains declarations for functions related to the initialization and processing of the + * web-based user interface (WebUI). It includes the necessary libraries and dependencies for handling + * web server functionality, asynchronous JSON operations, and live debugging through WebSockets. + * + * @author Marcel Peterkau + * @date 09.01.2024 + */ + #ifndef _WEBUI_H_ #define _WEBUI_H_ @@ -22,4 +35,4 @@ void Webserver_Process(); void Websocket_PushLiveDebug(String Message); -#endif \ No newline at end of file +#endif // _WEBUI_H_ diff --git a/Software/src/can.cpp b/Software/src/can.cpp index b5dadbc..05097a6 100644 --- a/Software/src/can.cpp +++ b/Software/src/can.cpp @@ -1,3 +1,17 @@ +/** + * @file can.cpp + * + * @brief Implementation file for CAN-related functions in the ChainLube application. + * + * This file contains the implementation of functions related to CAN (Controller Area Network) + * communication within the ChainLube application. It includes the initialization of the CAN module, + * setup of masks and filters, and processing of CAN messages. Additionally, a debug message function + * is included if CAN debugging is enabled. + * + * @author Your Name + * @date Date + */ + #include "can.h" MCP_CAN CAN0(GPIO_CS_CAN); @@ -6,9 +20,14 @@ MCP_CAN CAN0(GPIO_CS_CAN); void sendCANDebugMessage(); #endif +/** + * @brief Initializes the CAN module, sets masks, and filters based on the configured CAN source. + * + * This function initializes the CAN module, sets masks and filters based on the configured CAN source + * in the application settings, and sets the CAN module in normal mode for communication. + */ void Init_CAN() { - if (CAN0.begin(MCP_STDEXT, CAN_500KBPS, MCP_16MHZ) != CAN_OK) MaintainDTC(DTC_CAN_TRANSCEIVER_FAILED, true); @@ -30,6 +49,11 @@ void Init_CAN() CAN0.setMode(MCP_NORMAL); } +/** + * @brief Processes CAN messages and sends a CAN debug message periodically. + * + * This function processes CAN messages and sends a CAN debug message periodically based on a time interval. + */ void CAN_Process() { static uint32_t previousMillis = 0; @@ -40,7 +64,15 @@ void CAN_Process() previousMillis = millis(); } } - +/** + * @brief Processes CAN messages to determine the wheel speed based on the configured CAN source. + * + * This function reads incoming CAN messages and extracts the rear wheel speed information. + * The wheel speed is then converted to millimeters per second based on the configured CAN source. + * The function also monitors the CAN signal for potential issues and triggers diagnostic trouble codes (DTCs). + * + * @return The calculated distance traveled in millimeters since the last call. + */ uint32_t Process_CAN_WheelSpeed() { #define FACTOR_RWP_KMH_890ADV 18 // Divider to convert Raw Data to km/h @@ -87,6 +119,13 @@ uint32_t Process_CAN_WheelSpeed() } #ifdef CAN_DEBUG_MESSAGE +/** + * @brief Sends periodic CAN debug messages for monitoring and diagnostics. + * + * This function sends periodic CAN debug messages containing various system information for monitoring and diagnostics. + * The information includes system status, timestamps, tank percentage, DTC flags, and other relevant data. + * The debug messages are sent with a configurable multiplexer to broadcast different types of information in each cycle. + */ void sendCANDebugMessage() { #define MAX_DEBUG_MULTIPLEXER 6 diff --git a/Software/src/config.cpp b/Software/src/config.cpp index 482a5a6..041a462 100644 --- a/Software/src/config.cpp +++ b/Software/src/config.cpp @@ -1,24 +1,51 @@ +/** + * @file config.cpp + * @brief Implementation of EEPROM and configuration-related functions. + * + * This file contains functions for managing EEPROM storage and handling configuration data. + * It includes the definitions of configuration structures, EEPROM access, and utility functions. + */ + #include "config.h" #include "debugger.h" +// Instance of I2C_eeprom for EEPROM access I2C_eeprom ee(0x50, EEPROM_SIZE_BYTES); +// Configuration and persistence data structures LubeConfig_t LubeConfig; persistenceData_t PersistenceData; -const uint16_t eeVersion = 2; // inc + +// EEPROM version identifier +const uint16_t eeVersion = 2; // Increment this version when changing EEPROM structures + +// Flag indicating whether EEPROM is available boolean eeAvailable = false; +// Offsets within EEPROM for LubeConfig and PersistenceData const uint16_t startofLubeConfig = 16; const uint16_t startofPersistence = 16 + sizeof(LubeConfig) + (sizeof(LubeConfig) % 16); +// Function prototype to check EEPROM availability boolean checkEEPROMavailable(); +/** + * @brief Initializes EEPROM and checks its availability. + * + * This function initializes the EEPROM using the I2C_eeprom instance and checks if it's available. + */ void InitEEPROM() { ee.begin(); checkEEPROMavailable(); } +/** + * @brief Processes EEPROM actions based on the request from the global state. + * + * This function processes EEPROM actions based on the request from the global state. + * It performs actions such as saving, loading, and formatting EEPROM data for both configuration and persistence. + */ void EEPROM_Process() { switch (globals.requestEEAction) @@ -37,7 +64,7 @@ void EEPROM_Process() FormatConfig_EEPROM(); globals.requestEEAction = EE_IDLE; GetConfig_EEPROM(); - Debug_pushMessage("Formated EEPROM CFG\n"); + Debug_pushMessage("Formatted EEPROM CFG\n"); break; case EE_PDS_SAVE: StorePersistence_EEPROM(); @@ -53,7 +80,7 @@ void EEPROM_Process() FormatPersistence_EEPROM(); globals.requestEEAction = EE_IDLE; GetPersistence_EEPROM(); - Debug_pushMessage("Formated EEPROM PDS\n"); + Debug_pushMessage("Formatted EEPROM PDS\n"); break; case EE_FORMAT_ALL: FormatConfig_EEPROM(); @@ -61,7 +88,7 @@ void EEPROM_Process() GetConfig_EEPROM(); GetPersistence_EEPROM(); globals.requestEEAction = EE_IDLE; - Debug_pushMessage("Formated EEPROM ALL\n"); + Debug_pushMessage("Formatted EEPROM ALL\n"); break; case EE_ALL_SAVE: StorePersistence_EEPROM(); @@ -75,22 +102,36 @@ void EEPROM_Process() } } +/** + * @brief Stores the configuration data in EEPROM. + * + * This function calculates the checksum for the configuration data, updates it, and stores it in EEPROM. + * It also performs a sanity check on the configuration and raises a diagnostic trouble code (DTC) if needed. + */ void StoreConfig_EEPROM() { LubeConfig.checksum = 0; LubeConfig.checksum = Checksum_EEPROM((uint8_t *)&LubeConfig, sizeof(LubeConfig)); + if (!checkEEPROMavailable()) return; ee.updateBlock(startofLubeConfig, (uint8_t *)&LubeConfig, sizeof(LubeConfig)); uint32_t ConfigSanityCheckResult = ConfigSanityCheck(false); + if (ConfigSanityCheckResult > 0) { MaintainDTC(DTC_EEPROM_CFG_SANITY, true, ConfigSanityCheckResult); } } +/** + * @brief Retrieves the configuration data from EEPROM. + * + * This function reads the configuration data from EEPROM, performs a checksum validation, + * and conducts a sanity check on the configuration. It raises a diagnostic trouble code (DTC) if needed. + */ void GetConfig_EEPROM() { if (!checkEEPROMavailable()) @@ -105,15 +146,23 @@ void GetConfig_EEPROM() { MaintainDTC(DTC_EEPROM_CFG_BAD, true); } + LubeConfig.checksum = checksum; uint32_t ConfigSanityCheckResult = ConfigSanityCheck(false); + if (ConfigSanityCheckResult > 0) { MaintainDTC(DTC_EEPROM_CFG_SANITY, true, ConfigSanityCheckResult); } } +/** + * @brief Stores the persistence data in EEPROM. + * + * This function increments the write cycle counter, performs a checksum calculation on the persistence data, + * and stores it in EEPROM. It also handles EEPROM page movement when needed. + */ void StorePersistence_EEPROM() { if (PersistenceData.writeCycleCounter >= 0xFFF0) @@ -130,6 +179,13 @@ void StorePersistence_EEPROM() ee.updateBlock(globals.eePersistanceAdress, (uint8_t *)&PersistenceData, sizeof(PersistenceData)); } +/** + * @brief Retrieves the persistence data from EEPROM. + * + * This function reads the EEPROM to get the start address of the persistence data. + * If the start address is out of range, it resets and stores defaults. Otherwise, + * it reads from EEPROM and checks if the data is correct. + */ void GetPersistence_EEPROM() { if (!checkEEPROMavailable()) @@ -159,6 +215,11 @@ void GetPersistence_EEPROM() } } +/** + * @brief Formats the configuration partition in EEPROM. + * + * This function resets the configuration data to defaults and stores it in EEPROM. + */ void FormatConfig_EEPROM() { Debug_pushMessage("Formatting Config-Partition\n"); @@ -167,6 +228,11 @@ void FormatConfig_EEPROM() StoreConfig_EEPROM(); } +/** + * @brief Formats the persistence partition in EEPROM. + * + * This function resets the persistence data to defaults and stores it in EEPROM. + */ void FormatPersistence_EEPROM() { Debug_pushMessage("Formatting Persistance-Partition\n"); @@ -174,7 +240,13 @@ void FormatPersistence_EEPROM() // memset(&PersistenceData, 0, sizeof(PersistenceData)); StorePersistence_EEPROM(); } - +/** + * @brief Moves the persistence page in EEPROM. + * + * This function adjusts the persistence page address and resets the write cycle counter. + * + * @param reset If true, the function resets the persistence page address to the start of the partition. + */ void MovePersistencePage_EEPROM(boolean reset) { if (!checkEEPROMavailable()) @@ -183,7 +255,7 @@ void MovePersistencePage_EEPROM(boolean reset) globals.eePersistanceAdress += sizeof(PersistenceData); PersistenceData.writeCycleCounter = 0; - // check if we reached the End of the EEPROM and Startover at the beginning + // Check if we reached the end of the EEPROM and start over at the beginning if ((globals.eePersistanceAdress + sizeof(PersistenceData)) > ee.getDeviceSize() || reset) { globals.eePersistanceAdress = startofPersistence; @@ -192,25 +264,45 @@ void MovePersistencePage_EEPROM(boolean reset) ee.updateBlock(0, (uint8_t *)&globals.eePersistanceAdress, sizeof(globals.eePersistanceAdress)); } +/** + * @brief Calculate CRC-32 checksum for a block of data. + * + * This function implements the CRC-32 algorithm. + * + * @param data Pointer to the data block. + * @param len Length of the data block in bytes. + * @return CRC-32 checksum. + */ uint32_t Checksum_EEPROM(uint8_t const *data, size_t len) { if (data == NULL) return 0; - uint32_t crc, mask; - crc = 0xFFFFFFFF; + + uint32_t crc = 0xFFFFFFFF; + uint32_t mask; while (len--) { crc ^= *data++; + for (uint8_t k = 0; k < 8; k++) { mask = -(crc & 1); crc = (crc >> 1) ^ (0xEDB88320 & mask); } } + return ~crc; } +/** + * @brief Dump a portion of EEPROM contents for debugging. + * + * This function prints the contents of a specified portion of EEPROM in a formatted way. + * + * @param memoryAddress Starting address in EEPROM. + * @param length Number of bytes to dump. + */ void dumpEEPROM(uint16_t memoryAddress, uint16_t length) { #define BLOCK_TO_LENGTH 16 @@ -220,42 +312,79 @@ void dumpEEPROM(uint16_t memoryAddress, uint16_t length) char ascii_buf[BLOCK_TO_LENGTH + 1]; sprintf(ascii_buf, "%*s", BLOCK_TO_LENGTH, "ASCII"); + + // Print column headers Debug_pushMessage(PSTR("\nAddress ")); for (int x = 0; x < BLOCK_TO_LENGTH; x++) Debug_pushMessage("%3d", x); + // Align address and length to BLOCK_TO_LENGTH boundaries memoryAddress = memoryAddress / BLOCK_TO_LENGTH * BLOCK_TO_LENGTH; length = (length + BLOCK_TO_LENGTH - 1) / BLOCK_TO_LENGTH * BLOCK_TO_LENGTH; + // Iterate through the specified portion of EEPROM for (unsigned int i = 0; i < length; i++) { int blockpoint = memoryAddress % BLOCK_TO_LENGTH; + + // Print ASCII representation header for each block if (blockpoint == 0) { ascii_buf[BLOCK_TO_LENGTH] = 0; Debug_pushMessage(" %s", ascii_buf); Debug_pushMessage("\n0x%05X:", memoryAddress); } + + // Read and print each byte ascii_buf[blockpoint] = ee.readByte(memoryAddress); Debug_pushMessage(" %02X", ascii_buf[blockpoint]); + + // Replace non-printable characters with dots in ASCII representation if (ascii_buf[blockpoint] < 0x20 || ascii_buf[blockpoint] > 0x7E) ascii_buf[blockpoint] = '.'; + memoryAddress++; } + + // Print a new line at the end of the dump Debug_pushMessage("\n"); } +/** + * @brief Check if EEPROM is available and connected. + * + * This function checks if the EEPROM is available and connected. If not, it triggers + * a diagnostic trouble code (DTC) indicating the absence of EEPROM. + * + * @return true if EEPROM is available, false otherwise. + */ boolean checkEEPROMavailable() { + // Check if EEPROM is connected if (!ee.isConnected()) { + // Trigger DTC for no EEPROM found MaintainDTC(DTC_NO_EEPROM_FOUND, true); return false; } + + // Clear DTC for no EEPROM found since it's available now MaintainDTC(DTC_NO_EEPROM_FOUND, false); + + // EEPROM is available return true; } +/** + * @brief Perform sanity check on configuration settings. + * + * This function checks the validity of various configuration settings and returns a bitmask + * indicating which settings need to be reset. If autocorrect is enabled, it resets the settings + * to their default values. + * + * @param autocorrect If true, automatically correct invalid settings by resetting to defaults. + * @return A bitmask indicating which settings need to be reset. + */ uint32_t ConfigSanityCheck(bool autocorrect) { uint32_t setting_reset_bits = 0; @@ -332,7 +461,7 @@ uint32_t ConfigSanityCheck(bool autocorrect) LubeConfig.DistancePerRevolution_mm = LubeConfig_defaults.DistancePerRevolution_mm; } } - + if (!(LubeConfig.BleedingPulses > 0) || !(LubeConfig.BleedingPulses < 1001)) { SET_BIT(setting_reset_bits, 10); @@ -360,5 +489,6 @@ uint32_t ConfigSanityCheck(bool autocorrect) if (autocorrect) LubeConfig.CANSource = LubeConfig_defaults.CANSource; } + // Return the bitmask indicating which settings need to be reset return setting_reset_bits; } \ No newline at end of file diff --git a/Software/src/debugger.cpp b/Software/src/debugger.cpp index 768db0e..e2d3bea 100644 --- a/Software/src/debugger.cpp +++ b/Software/src/debugger.cpp @@ -1,3 +1,16 @@ +/** + * @file debugger.cpp + * @brief Implementation of debugging functions for monitoring and diagnostics. + * + * This file contains the implementation of various debugging functions to monitor + * and diagnose the system. It includes functions to print system information, WiFi + * details, EEPROM status, dump configuration settings, dump persistence data, show + * Diagnostic Trouble Codes (DTCs), and more. + * + * @author Marcel Peterkau + * @date 09.04.2024 + */ + #include "debugger.h" DebugStatus_t DebuggerStatus[dbg_cntElements]; @@ -15,32 +28,45 @@ void Debug_ShowDTCs(); void Debug_dumpGlobals(); void Debug_printHelp(); +/** + * @brief Initializes the debugger by setting the initial status for different debug ports. + * Serial debug output is turned off. + */ void initDebugger() { + // Set the initial status of debug ports DebuggerStatus[dbg_Serial] = disabled; DebuggerStatus[dbg_Webui] = disabled; + // Disable serial debug output Serial.setDebugOutput(false); } - +/** + * @brief Processes incoming debug commands from the Serial interface. + * It reads characters from Serial and interprets them as commands. + * The recognized commands are processed accordingly. + */ void Debug_Process() { + // Enumeration for tracking the state of input processing typedef enum InputProcessed_e { - IDLE, - CMD_COMPLETE, - CMD_ABORT, - CMD_OVERFLOW + IDLE, ///< No command processing is in progress + CMD_COMPLETE, ///< Received a complete command + CMD_ABORT, ///< Received an abort command (Esc) + CMD_OVERFLOW ///< Input buffer overflow occurred } InputProcessed_t; - static unsigned int inputCnt = 0; - static char inputBuffer[32]; - InputProcessed_t InputProcessed = IDLE; + static unsigned int inputCnt = 0; ///< Counter for characters in the input buffer + static char inputBuffer[32]; ///< Buffer to store the received characters + InputProcessed_t InputProcessed = IDLE; ///< State variable for input processing + // Check if there are characters available in the Serial input buffer if (Serial.available()) { char inputChar = Serial.read(); + // Process the received character based on its value switch (inputChar) { case '\n': @@ -55,7 +81,7 @@ void Debug_Process() InputProcessed = CMD_ABORT; break; - case 0x21 ... 0x7E: // its a real letter or sign and not some control-chars + case 0x21 ... 0x7E: // it's a real letter or sign and not some control-chars inputBuffer[inputCnt] = inputChar; inputCnt++; break; @@ -64,6 +90,7 @@ void Debug_Process() break; } + // Check for input buffer overflow if (inputCnt > sizeof(inputBuffer)) { inputCnt = 0; @@ -72,6 +99,7 @@ void Debug_Process() } } + // Process the command based on the detected state of input processing switch (InputProcessed) { case CMD_ABORT: @@ -83,7 +111,7 @@ void Debug_Process() break; case CMD_OVERFLOW: - Debug_pushMessage("input Buffer overflow\n"); + Debug_pushMessage("Input buffer overflow\n"); break; default: @@ -91,32 +119,53 @@ void Debug_Process() } InputProcessed = IDLE; } - +/** + * @brief Sets the status of a specific debug port (Serial or WebUI). + * Updates the status in the DebuggerStatus array and provides debug messages. + * + * @param port The debug port to set the status for (dbg_Serial or dbg_Webui). + * @param status The status to set (enabled or disabled). + */ void SetDebugportStatus(DebugPorts_t port, DebugStatus_t status) { + // Display a debug message based on the provided status if (status == disabled) - Debug_pushMessage("disable DebugPort %s\n", sDebugPorts[port]); + Debug_pushMessage("Disable DebugPort %s\n", sDebugPorts[port]); + // Update the status in the DebuggerStatus array DebuggerStatus[port] = status; + // Display a debug message based on the updated status if (status == enabled) - Debug_pushMessage("enabled DebugPort %s\n", sDebugPorts[port]); + Debug_pushMessage("Enabled DebugPort %s\n", sDebugPorts[port]); } +/** + * @brief Pushes a formatted debug message to the enabled debug ports (Serial or WebUI). + * + * @param format The format string for the debug message. + * @param ... Additional arguments for formatting the message. + */ void Debug_pushMessage(const char *format, ...) { + // Check if either the Serial or WebUI debug port is enabled if ((DebuggerStatus[dbg_Serial] == enabled) || (DebuggerStatus[dbg_Webui] == enabled)) { - char buff[64]; - va_list arg; + char buff[64]; // Buffer to hold the formatted message + va_list arg; // Variable argument list for vsnprintf va_start(arg, format); + + // Format the message and store it in the buffer vsnprintf(buff, sizeof(buff), format, arg); va_end(arg); + // Send the message to the Serial debug port if enabled if (DebuggerStatus[dbg_Serial] == enabled) { Serial.print(buff); } + + // Push the message to the WebUI debug port if enabled if (DebuggerStatus[dbg_Webui] == enabled) { Websocket_PushLiveDebug(String(buff)); @@ -124,12 +173,22 @@ void Debug_pushMessage(const char *format, ...) } } +/** + * @brief Pushes a formatted CAN debug message to the enabled debug ports (Serial or WebUI). + * + * @param id CAN message ID. + * @param dlc Data Length Code of the CAN message. + * @param data Pointer to the data array of the CAN message. + */ void pushCANDebug(uint32_t id, uint8_t dlc, uint8_t *data) { + // Check if either the Serial or WebUI debug port is enabled if ((DebuggerStatus[dbg_Serial] == enabled) || (DebuggerStatus[dbg_Webui] == enabled)) { - char buff[100]; - char *p = buff; + char buff[100]; // Buffer to hold the formatted message + char *p = buff; // Pointer to navigate the buffer + + // Format the CAN message information into the buffer p += snprintf(p, sizeof(buff), "CAN: 0x%08X | %d | ", id, dlc); for (int i = 0; i < dlc; i++) { @@ -138,10 +197,13 @@ void pushCANDebug(uint32_t id, uint8_t dlc, uint8_t *data) *(p++) = '\n'; *p = '\0'; + // Send the formatted CAN message to the Serial debug port if enabled if (DebuggerStatus[dbg_Serial] == enabled) { Serial.print(buff); } + + // Push the formatted CAN message to the WebUI debug port if enabled if (DebuggerStatus[dbg_Webui] == enabled) { Websocket_PushLiveDebug(String(buff)); @@ -149,8 +211,14 @@ void pushCANDebug(uint32_t id, uint8_t dlc, uint8_t *data) } } +/** + * @brief Processes a debug command and performs corresponding actions. + * + * @param command The debug command to be processed. + */ void processCmdDebug(String command) { + // Check the received command and execute corresponding actions if (command == "help") Debug_printHelp(); else if (command == "sysinfo") @@ -193,18 +261,29 @@ void processCmdDebug(String command) Debug_pushMessage("unknown Command\n"); } +/** + * @brief Formats the Config-EEPROM and resets it to default values. + * Prints a debug message after formatting. + */ void Debug_formatCFG() { - Debug_pushMessage("Formatting Config-EEPROM and reseting to default\n"); + Debug_pushMessage("Formatting Config-EEPROM and resetting to default\n"); FormatConfig_EEPROM(); } +/** + * @brief Formats the Persistence-EEPROM and resets it to default values. + * Prints a debug message after formatting. + */ void Debug_formatPersistence() { - Debug_pushMessage("Formatting Persistence-EEPROM and reseting to default\n"); + Debug_pushMessage("Formatting Persistence-EEPROM and resetting to default\n"); FormatPersistence_EEPROM(); } +/** + * @brief Prints system information and status to the debug output. + */ void Debug_printSystemInfo() { Debug_pushMessage("Souko's ChainOiler Mk1\n"); @@ -224,10 +303,13 @@ void Debug_printSystemInfo() : ideMode == FM_DOUT ? "DOUT" : "UNKNOWN")); Debug_pushMessage("OTA-Pass: %s\n", QUOTE(ADMIN_PASSWORD)); - Debug_pushMessage("Git-Revison: %s\n", constants.GitHash); + Debug_pushMessage("Git-Revision: %s\n", constants.GitHash); Debug_pushMessage("Sw-Version: %d.%02d\n", constants.FW_Version_major, constants.FW_Version_minor); } +/** + * @brief Dumps the current configuration parameters to the debug output. + */ void Debug_dumpConfig() { Debug_pushMessage("DistancePerLube_Default: %d\n", LubeConfig.DistancePerLube_Default); @@ -237,7 +319,7 @@ void Debug_dumpConfig() Debug_pushMessage("TankRemindAtPercentage: %d\n", LubeConfig.TankRemindAtPercentage); Debug_pushMessage("PulsePerRevolution: %d\n", LubeConfig.PulsePerRevolution); Debug_pushMessage("TireWidth_mm: %d\n", LubeConfig.TireWidth_mm); - Debug_pushMessage("TireWidthHeight_Ratio: %d\n", LubeConfig.TireWidth_mm); + Debug_pushMessage("TireWidthHeight_Ratio: %d\n", LubeConfig.TireWidthHeight_Ratio); Debug_pushMessage("RimDiameter_Inch: %d\n", LubeConfig.RimDiameter_Inch); Debug_pushMessage("DistancePerRevolution_mm: %d\n", LubeConfig.DistancePerRevolution_mm); Debug_pushMessage("BleedingPulses: %d\n", LubeConfig.BleedingPulses); @@ -247,6 +329,9 @@ void Debug_dumpConfig() Debug_pushMessage("checksum: 0x%08X\n", LubeConfig.checksum); } +/** + * @brief Dumps the global variables and their values to the debug output. + */ void Debug_dumpGlobals() { Debug_pushMessage("systemStatus: %d\n", globals.systemStatus); @@ -261,6 +346,9 @@ void Debug_dumpGlobals() Debug_pushMessage("hasDTC: %d\n", globals.hasDTC); } +/** + * @brief Dumps the persistence data variables and their values to the debug output. + */ void Debug_dumpPersistance() { Debug_pushMessage("writeCycleCounter: %d\n", PersistenceData.writeCycleCounter); @@ -270,12 +358,21 @@ void Debug_dumpPersistance() Debug_pushMessage("PSD Adress: 0x%04X\n", globals.eePersistanceAdress); } +/** + * @brief Prints information related to WiFi to the debug output. + */ void Debug_printWifiInfo() { + // Add relevant code here if needed } +/** + * @brief Checks the EEPROM data integrity by calculating and comparing checksums. + * Prints the result to the debug output. + */ void Debug_CheckEEPOM() { + // Check PersistenceData EEPROM checksum uint32_t checksum = PersistenceData.checksum; PersistenceData.checksum = 0; @@ -290,6 +387,7 @@ void Debug_CheckEEPOM() PersistenceData.checksum = checksum; + // Check LubeConfig EEPROM checksum checksum = LubeConfig.checksum; LubeConfig.checksum = 0; @@ -304,24 +402,32 @@ void Debug_CheckEEPOM() LubeConfig.checksum = checksum; } +/** + * @brief Displays Diagnostic Trouble Codes (DTCs) along with their timestamps, + * status, and severity in a formatted manner. + */ void Debug_ShowDTCs() { char buff_timestamp[16]; // Format: DD-hh:mm:ss:xxx char buff_active[9]; + // Header for the DTC display Debug_pushMessage("\n timestamp | DTC-Nr. | status | severity\n"); + // Iterate through DTCStorage and display each entry for (uint32_t i = 0; i < MAX_DTC_STORAGE; i++) { if (DTCStorage[i].Number < DTC_LAST_DTC) { + // Format timestamp sprintf(buff_timestamp, "%02d-%02d:%02d:%02d:%03d", DTCStorage[i].timestamp / 86400000, // Days DTCStorage[i].timestamp / 360000 % 24, // Hours DTCStorage[i].timestamp / 60000 % 60, // Minutes DTCStorage[i].timestamp / 1000 % 60, // Seconds - DTCStorage[i].timestamp % 1000); // milliseconds + DTCStorage[i].timestamp % 1000); // Milliseconds + // Determine DTC status if (DTCStorage[i].active == DTC_ACTIVE) strcpy(buff_active, "active"); else if (DTCStorage[i].active == DTC_PREVIOUS) @@ -329,19 +435,28 @@ void Debug_ShowDTCs() else strcpy(buff_active, "none"); + // Display DTC information Debug_pushMessage("%s %7d %8s %8d\n", buff_timestamp, DTCStorage[i].Number, buff_active); } } } +/** + * @brief Displays the help commands for debugging through Serial or WebUI. + * Each command is printed individually in a formatted manner. + */ void Debug_printHelp() { char buff[64]; - for (unsigned int i = sizeof(helpCmd) / 63; i < sizeof(helpCmd) / 63; i++) + // Iterate through helpCmd and display each command + for (unsigned int i = 0; i < sizeof(helpCmd) / 63; i++) { + // Copy a portion of helpCmd to buff for display memcpy_P(buff, (helpCmd + (i * 63)), 63); buff[63] = 0; + + // Display the help command Debug_pushMessage(buff); } -} \ No newline at end of file +} diff --git a/Software/src/dtc.cpp b/Software/src/dtc.cpp index 7e0b327..1fb949a 100644 --- a/Software/src/dtc.cpp +++ b/Software/src/dtc.cpp @@ -1,14 +1,37 @@ +/** + * @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); @@ -16,21 +39,23 @@ void MaintainDTC(DTCNum_t DTC_no, boolean active, uint32_t DebugValue) 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; + return; // DTC found and processed, exit the function } } - // DTC was not found with upper iteration, but is active - // so we need to look for free space to store DTC + // 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); @@ -38,12 +63,20 @@ void MaintainDTC(DTCNum_t DTC_no, boolean active, uint32_t DebugValue) DTCStorage[i].timestamp = millis(); DTCStorage[i].active = DTC_ACTIVE; DTCStorage[i].debugVal = DebugValue; - return; + 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++) @@ -57,6 +90,12 @@ void ClearDTC(DTCNum_t DTC_no) } } +/** + * @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++) @@ -67,6 +106,15 @@ void ClearAllDTC() } } +/** + * @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; @@ -87,6 +135,15 @@ DTCNum_t getlastDTC(boolean only_active) 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++) @@ -99,6 +156,16 @@ DTCSeverity_t getSeverityForDTC(DTCNum_t targetCode) 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; @@ -120,10 +187,10 @@ void DTC_Process() else { globals.hasDTC = false; - + if (globals.systemStatus == sysStat_Error) { globals.systemStatus = preserverSysStatusError; } } -} \ No newline at end of file +} diff --git a/Software/src/globals.cpp b/Software/src/globals.cpp index c202307..01bba72 100644 --- a/Software/src/globals.cpp +++ b/Software/src/globals.cpp @@ -1,7 +1,23 @@ +/** + * @file globals.cpp + * @brief Implementation of global variables and initialization functions. + * + * This file defines and initializes the global variables used throughout the project. + * The global variables are encapsulated in the Globals_t structure. The initGlobals function + * is responsible for initializing these variables to their default values during system startup. + */ + #include "globals.h" +// Global instance of the Globals_t structure Globals_t globals; +/** + * @brief Initializes global variables to default values during system startup. + * + * This function sets the initial values for various global variables, ensuring proper + * initialization of system-wide parameters. + */ void initGlobals() { globals.purgePulses = 0; diff --git a/Software/src/gps.cpp b/Software/src/gps.cpp index c02c9a7..5906687 100644 --- a/Software/src/gps.cpp +++ b/Software/src/gps.cpp @@ -1,7 +1,26 @@ +/** + * @file gps.cpp + * + * @brief Implementation file for GPS-related functions in the ChainLube application. + * + * This file contains the implementation of functions related to GPS functionality within the ChainLube + * application. It includes the initialization of the GPS module, processing GPS data for wheel speed, + * and maintaining Diagnostic Trouble Codes (DTCs) based on GPS communication status. + * + * @author Marcel Peterkau + * @date 09.01.2024 + */ + #include "gps.h" TinyGPSPlus gps; +/** + * @brief Initializes the GPS module with the specified baud rate. + * + * This function initializes the GPS module with the baud rate configured in the application settings. + * It also prints a debug message indicating the initialization status. + */ void Init_GPS() { uint32_t baudrate; @@ -22,6 +41,15 @@ void Init_GPS() Serial.begin(baudrate); } +/** + * @brief Processes GPS data to calculate rear wheel speed and returns the distance traveled. + * + * This function processes GPS data received from the GPS module, calculates the rear wheel speed in + * kilometers per hour, and returns the distance traveled based on the speed and time elapsed since + * the last valid speed measurement. + * + * @return The distance traveled in millimeters since the last GPS speed measurement. + */ uint32_t Process_GPS_WheelSpeed() { static uint32_t lastRecTimestamp; @@ -49,7 +77,9 @@ uint32_t Process_GPS_WheelSpeed() lastRecTimestamp = millis(); } } + + // Maintain DTC for no GPS data received within a certain time frame MaintainDTC(DTC_NO_GPS_SERIAL, (millis() > lastRecTimestamp + 10000)); return 0; -} \ No newline at end of file +} diff --git a/Software/src/lubeapp.cpp b/Software/src/lubeapp.cpp index 028b5be..350ef88 100644 --- a/Software/src/lubeapp.cpp +++ b/Software/src/lubeapp.cpp @@ -1,28 +1,56 @@ +/** + * @file lubeapp.cpp + * + * @brief Implementation file for the ChainLube application logic. + * + * This file contains the implementation of the ChainLube application logic, including functions + * for running the main application, initiating lubrication pulses, and maintaining system status. + * Global variables related to lubrication pulses are also defined in this file. + * + * @author Marcel Peterkau + * @date 09.01.2024 + */ + #include "lubeapp.h" uint32_t lubePulseTimestamp = 0; +/** + * @brief Runs the main logic of the ChainLube application based on the current system status. + * + * This function is responsible for executing the main logic of the ChainLube application. It calculates + * the tank percentage, maintains Diagnostic Trouble Codes (DTCs) related to the tank level, updates travel + * distances, triggers lubrication pulses, and handles the behavior based on the current system status + * (Startup, Normal, Rain, Purge, Error, Shutdown). It also manages the pin state of the lube pump. + * + * @param add_milimeters The additional distance traveled in millimeters to be processed by the application. + */ void RunLubeApp(uint32_t add_milimeters) { - + // Calculate and update tank percentage globals.TankPercentage = PersistenceData.tankRemain_microL / (LubeConfig.tankCapacity_ml * 10); + // Maintain DTCs related to tank level MaintainDTC(DTC_TANK_EMPTY, (PersistenceData.tankRemain_microL < LubeConfig.amountPerDose_microL)); MaintainDTC(DTC_TANK_LOW, (globals.TankPercentage < LubeConfig.TankRemindAtPercentage)); - // Add traveled Distance in mm + // Add traveled distance in millimeters PersistenceData.TravelDistance_highRes_mm += add_milimeters; PersistenceData.odometer_mm += add_milimeters; + + // Update odometer if necessary if (PersistenceData.odometer_mm >= 1000000) { PersistenceData.odometer++; PersistenceData.odometer_mm = 0; } + // Handle different system statuses switch (globals.systemStatus) { case sysStat_Startup: strcpy_P(globals.systemStatustxt, PSTR("Startup")); + // Transition to Normal status after startup delay if (millis() > STARTUP_DELAY) { globals.systemStatus = sysStat_Normal; @@ -32,6 +60,7 @@ void RunLubeApp(uint32_t add_milimeters) case sysStat_Normal: strcpy_P(globals.systemStatustxt, PSTR("Normal")); + // Trigger lube pulse if traveled distance exceeds the configured limit if (PersistenceData.TravelDistance_highRes_mm / 1000 > LubeConfig.DistancePerLube_Default) { LubePulse(); @@ -41,16 +70,20 @@ void RunLubeApp(uint32_t add_milimeters) case sysStat_Rain: strcpy_P(globals.systemStatustxt, PSTR("Rain")); + // Trigger lube pulse if traveled distance exceeds the configured limit in Rain mode if (PersistenceData.TravelDistance_highRes_mm / 1000 > LubeConfig.DistancePerLube_Rain) { LubePulse(); PersistenceData.TravelDistance_highRes_mm = 0; } break; + case sysStat_Purge: strcpy_P(globals.systemStatustxt, PSTR("Purge")); + // Execute lube pulses during the Purge status if (globals.purgePulses > 0) { + // Check if enough time has passed since the last lube pulse if (lubePulseTimestamp + LUBE_PULSE_PAUSE_MS < millis()) { LubePulse(); @@ -60,35 +93,48 @@ void RunLubeApp(uint32_t add_milimeters) } else { + // Transition back to the previous status after completing purge pulses globals.systemStatus = globals.resumeStatus; } break; + case sysStat_Error: strcpy_P(globals.systemStatustxt, PSTR("Error")); break; + case sysStat_Shutdown: strcpy_P(globals.systemStatustxt, PSTR("Shutdown")); break; + default: break; } - // maintain Pin-State of Lube-Pump + // Maintain Pin-State of Lube-Pump if (lubePulseTimestamp > millis()) digitalWrite(GPIO_PUMP, HIGH); else digitalWrite(GPIO_PUMP, LOW); } +/** + * @brief Initiates a lubrication pulse if there is sufficient oil remaining in the tank. + * + * This function checks if there is enough oil remaining in the tank to perform a lubrication pulse. + * If there is sufficient oil, it updates the lubePulseTimestamp to trigger the pulse and decreases + * the tank oil level by the configured amount per dose (LubeConfig.amountPerDose_microL). + */ void LubePulse() { - if (PersistenceData.tankRemain_microL > 0) // Only Lube if theres Oil remaining! + // Only initiate a lubrication pulse if there is oil remaining in the tank + if (PersistenceData.tankRemain_microL > 0) { lubePulseTimestamp = millis() + LUBE_PULSE_LENGHT_MS; - if (PersistenceData.tankRemain_microL < LubeConfig.amountPerDose_microL) // Prevent underrun and shiftover + // Prevent underrun and shift over by adjusting the tank oil level + if (PersistenceData.tankRemain_microL < LubeConfig.amountPerDose_microL) PersistenceData.tankRemain_microL = 0; else - PersistenceData.tankRemain_microL = PersistenceData.tankRemain_microL - LubeConfig.amountPerDose_microL; + PersistenceData.tankRemain_microL -= LubeConfig.amountPerDose_microL; } -} \ No newline at end of file +} diff --git a/Software/src/main.cpp b/Software/src/main.cpp index d899a3b..5f15bfb 100644 --- a/Software/src/main.cpp +++ b/Software/src/main.cpp @@ -1,3 +1,18 @@ +/** + * @file main.cpp + * + * @brief Main source file for the Souko's ChainLube Mk1 ESP8266 project. + * + * This file includes necessary libraries, defines configuration options, and declares global variables + * and function prototypes. It sets up essential components, initializes peripherals, and defines + * callbacks for interrupt service routines (ISRs) and timers. The main setup function configures the + * project, and the loop function handles the main execution loop, performing various tasks based on + * the configured options. + * + * @author Marcel Peterkau + * @date 09.01.2024 + */ + #include #include #ifdef FEATURE_ENABLE_OLED @@ -57,28 +72,49 @@ Ticker WiFiMaintainConnectionTicker(wifiMaintainConnectionTicker_callback, 1000, #endif Ticker EEPROMCyclicPDSTicker(EEPROMCyclicPDS_callback, 60000, 0, MILLIS); +/** + * @brief Initializes the ESP8266 project, configuring various components and setting up required services. + * + * This setup function is responsible for initializing the ESP8266 project, including setting the CPU frequency, + * configuring WiFi settings, initializing DTC storage, handling WiFi client functionality (if enabled), + * initializing the Serial communication, setting up an OLED display (if enabled), initializing EEPROM, + * loading configuration and persistence data from EEPROM, initializing LEDs, setting up the chosen speed source + * (CAN, GPS, Impulse), configuring GPIO pins, setting up Over-The-Air (OTA) updates, initializing the web user interface, + * initializing global variables, starting cyclic EEPROM updates for Persistence Data Structure (PDS), and printing + * initialization status messages to Serial. + */ void setup() { + // Set CPU frequency to 80MHz system_update_cpu_freq(SYS_CPU_80MHZ); + + // Generate a unique device name based on ESP chip ID snprintf(globals.DeviceName, 32, HOST_NAME, ESP.getChipId()); + + // Disable WiFi persistent storage WiFi.persistent(false); - ClearAllDTC(); // Init DTC-Storage + // Initialize and clear Diagnostic Trouble Code (DTC) storage + ClearAllDTC(); #ifdef FEATURE_ENABLE_WIFI_CLIENT + // Configure WiFi settings for client mode if enabled WiFi.mode(WIFI_STA); WiFi.setHostname(globals.DeviceName); wifiMulti.addAP(QUOTE(WIFI_SSID_CLIENT), QUOTE(WIFI_PASSWORD_CLIENT)); WiFiMaintainConnectionTicker.start(); #else + // Disable WiFi if WiFi client feature is not enabled WiFi.mode(WIFI_OFF); #endif + // Initialize Serial communication Serial.begin(115200); Serial.print("\n\nSouko's ChainLube Mk1\n"); Serial.print(globals.DeviceName); #ifdef FEATURE_ENABLE_OLED + // Initialize OLED display if enabled u8x8.begin(); u8x8.setFont(u8x8_font_chroma48medium8_r); u8x8.clearDisplay(); @@ -87,14 +123,17 @@ void setup() Serial.print("\nDisplay-Init done"); #endif + // Initialize EEPROM, load configuration, and persistence data from EEPROM InitEEPROM(); GetConfig_EEPROM(); GetPersistence_EEPROM(); Serial.print("\nEE-Init done"); + // Initialize LEDs leds.begin(); Serial.print("\nLED-Init done"); + // Initialize based on the chosen speed source (CAN, GPS, Impulse) switch (LubeConfig.SpeedSource) { case SOURCE_CAN: @@ -115,13 +154,18 @@ void setup() } Serial.print("\nSource-Init done"); + + // Configure GPIO pins for button and pump control pinMode(GPIO_BUTTON, INPUT_PULLUP); pinMode(GPIO_PUMP, OUTPUT); + // Set up OTA updates ArduinoOTA.setPort(8266); ArduinoOTA.setHostname(globals.DeviceName); ArduinoOTA.setPassword(QUOTE(ADMIN_PASSWORD)); + #ifdef FEATURE_ENABLE_OLED + // Set up OTA callbacks for OLED display if enabled ArduinoOTA.onStart([]() { u8x8.clearDisplay(); @@ -148,20 +192,40 @@ void setup() u8x8.drawString(0, 0, "OTA-Restart"); u8x8.refreshDisplay(); }); #endif + + // Begin OTA updates ArduinoOTA.begin(); Serial.print("\nOTA-Init done"); + + // Initialize the web user interface initWebUI(); Serial.print("\nWebUI-Init done"); + + // Initialize global variables initGlobals(); Serial.print("\nglobals-Init done"); + + // Start cyclic EEPROM updates for Persistence Data Structure (PDS) EEPROMCyclicPDSTicker.start(); Serial.print("\nSetup Done\n"); } +/** + * @brief Main execution loop for the ESP8266 project, performing various tasks based on configuration. + * + * This loop function handles different tasks based on the configured source of speed data (impulse, CAN, time, GPS). + * It calculates wheel distance, runs the lubrication application, updates the OLED display (if enabled), + * processes CAN messages, handles button input, manages LED behavior, performs EEPROM-related tasks, handles + * webserver operations, processes Diagnostic Trouble Codes (DTC), and manages debugging. Additionally, it + * integrates functionalities such as Over-The-Air (OTA) updates, cyclic EEPROM updates for Persistence Data + * Structure (PDS), WiFi connection maintenance, and system shutdown handling. + */ void loop() { + // Variable to store calculated wheel distance uint32_t wheelDistance = 0; + // Switch based on the configured speed source switch (LubeConfig.SpeedSource) { case SOURCE_IMPULSE: @@ -180,14 +244,22 @@ void loop() break; } + // Run lubrication application with the calculated wheel distance RunLubeApp(wheelDistance); + #ifdef FEATURE_ENABLE_OLED + // Update OLED display if enabled Display_Process(); #endif + + // Process CAN messages if the speed source is not impulse if (LubeConfig.SpeedSource != SOURCE_IMPULSE) { CAN_Process(); } + + // Process button input, manage LED behavior, perform EEPROM tasks, handle webserver operations, + // process Diagnostic Trouble Codes (DTC), and manage debugging Button_Process(); LED_Process(); EEPROM_Process(); @@ -195,18 +267,35 @@ void loop() DTC_Process(); Debug_Process(); + // Handle OTA updates and update cyclic EEPROM tasks for Persistence Data Structure (PDS) ArduinoOTA.handle(); EEPROMCyclicPDSTicker.update(); + #ifdef FEATURE_ENABLE_WIFI_CLIENT + // Update WiFi connection maintenance ticker if WiFi client feature is enabled WiFiMaintainConnectionTicker.update(); #endif + + // Perform system shutdown if the status is set to shutdown if (globals.systemStatus == sysStat_Shutdown) - SystemShutdown(); + SystemShutdown(false); + + // Yield to allow other tasks to run yield(); } +/** + * @brief Converts an IPAddress object to a String representation. + * + * This function takes an IPAddress object and converts it into a String representing + * the IPv4 address. Each octet of the address is separated by a dot. + * + * @param ipAddress The IPAddress object to be converted. + * @return A String representing the IPv4 address. + */ String IpAddress2String(const IPAddress &ipAddress) { + // Concatenate each octet of the IPAddress with dots in between return String(ipAddress[0]) + String(".") + String(ipAddress[1]) + String(".") + String(ipAddress[2]) + String(".") + @@ -214,42 +303,80 @@ String IpAddress2String(const IPAddress &ipAddress) } #ifdef FEATURE_ENABLE_WIFI_CLIENT +/** + * @brief Callback function for maintaining WiFi connection and handling connection failures. + * + * This callback function is used by a ticker to periodically check the WiFi connection status. + * If the device is not connected to WiFi, it counts connection failures. If the number of failures + * exceeds a defined threshold, the function triggers the initiation of an Access Point (AP) mode + * using the `toggleWiFiAP` function. + */ void wifiMaintainConnectionTicker_callback() { + // Static variables to track WiFi connection failure count and maximum allowed failures static uint32_t WiFiFailCount = 0; const uint32_t WiFiFailMax = 20; + // Check if the device is connected to WiFi if (wifiMulti.run(connectTimeoutMs) == WL_CONNECTED) { - return; + return; // Exit if connected } else { + // Increment WiFi connection failure count if (WiFiFailCount < WiFiFailMax) { WiFiFailCount++; } else { + // Trigger AP mode if the maximum failures are reached Debug_pushMessage("WiFi not connected! - Start AP"); toggleWiFiAP(); } } } + #endif +/** + * @brief Callback function for cyclically storing Persistence Data Structure (PDS) to EEPROM. + * + * This callback function is invoked periodically to store the Persistence Data Structure (PDS) + * to the EEPROM. It ensures that essential data is saved persistently, allowing the system to + * recover its state after power cycles or resets. + */ void EEPROMCyclicPDS_callback() { StorePersistence_EEPROM(); } +/** + * @brief Interrupt Service Routine (ISR) triggered by wheel speed sensor pulses. + * + * This ISR is called whenever a pulse is detected from the wheel speed sensor. It increments + * the `wheel_pulse` variable, which is used to track the number of pulses received. + */ void trigger_ISR() { wheel_pulse++; } +/** + * @brief Manages LED behavior based on the current system status and user overrides. + * + * This function handles LED behavior, including startup animations, confirmation animations for + * normal and rain modes, indication for purge, error, shutdown, and normal operation. It supports + * user overrides to set a specific LED color. The LED status is determined by the current system + * status, and specific LED patterns are displayed accordingly. + * + * @param override Flag indicating whether to override the LED behavior (0: No override, 1: Override, 2: Resume previous state). + * @param SetColor The color to set when overriding the LED behavior. + */ void LED_Process(uint8_t override, uint32_t SetColor) { + // Enumeration to represent LED status typedef enum { LED_Startup, @@ -263,17 +390,20 @@ void LED_Process(uint8_t override, uint32_t SetColor) LED_Override } tLED_Status; + // Static variables to track LED status, system status, override color, and previous LED status static tSystem_Status oldSysStatus = sysStat_Startup; static tLED_Status LED_Status = LED_Startup; static uint32_t LED_override_color = 0; static tLED_Status LED_ResumeOverrideStatus = LED_Startup; + // Variables for managing LED animation timing uint8_t color = 0; uint32_t timer = 0; uint32_t animtimer = 0; static uint32_t timestamp = 0; timer = millis(); + // Handle LED overrides if (override == 1) { if (LED_Status != LED_Override) @@ -294,6 +424,7 @@ void LED_Process(uint8_t override, uint32_t SetColor) } } + // Update LED status when system status changes if (oldSysStatus != globals.systemStatus) { switch (globals.systemStatus) @@ -330,6 +461,7 @@ void LED_Process(uint8_t override, uint32_t SetColor) oldSysStatus = globals.systemStatus; } + // Handle different LED statuses switch (LED_Status) { case LED_Startup: @@ -433,28 +565,47 @@ void LED_Process(uint8_t override, uint32_t SetColor) } leds.show(); } + #ifdef FEATURE_ENABLE_OLED +/** + * @brief Manages the display content based on the current system status and updates the OLED display. + * + * This function handles the content to be displayed on the OLED screen, taking into account the + * current system status. It clears the display and prints relevant information such as system mode, + * remaining lubrication distance, tank level, WiFi status, speed source, and IP address. Additionally, + * it refreshes the OLED display with the updated content. + */ void Display_Process() { + // Static variable to track the previous system status static tSystem_Status oldSysStatus = sysStat_Startup; + // Check if the system status has changed since the last update if (oldSysStatus != globals.systemStatus) { + // Clear the display and print the system title when the status changes u8x8.clearDisplay(); u8x8.drawString(0, 0, "KTM ChainLube V1"); oldSysStatus = globals.systemStatus; } + // Set the cursor position for displaying information on the OLED screen u8x8.setCursor(0, 1); + + // Calculate remaining lubrication distance based on system mode uint32_t DistRemain = globals.systemStatus == sysStat_Normal ? LubeConfig.DistancePerLube_Default : LubeConfig.DistancePerLube_Rain; DistRemain = DistRemain - (PersistenceData.TravelDistance_highRes_mm / 1000); + + // Display relevant information on the OLED screen based on system status u8x8.printf(PSTR("Mode: %10s\n"), globals.systemStatustxt); if (globals.systemStatus == sysStat_Error) { + // Display the last Diagnostic Trouble Code (DTC) in case of an error u8x8.printf(PSTR("last DTC: %6d\n"), getlastDTC(false)); } else { + // Display information such as next lubrication distance, tank level, WiFi status, speed source, and IP address u8x8.printf(PSTR("next Lube: %4dm\n"), DistRemain); u8x8.printf(PSTR("Tank: %8dml\n"), PersistenceData.tankRemain_microL / 1000); u8x8.printf(PSTR("WiFi: %10s\n"), (WiFi.getMode() == WIFI_AP ? "AP" : WiFi.getMode() == WIFI_OFF ? "OFF" @@ -463,18 +614,29 @@ void Display_Process() u8x8.printf(PSTR("Source: %8s\n"), SpeedSourceString[LubeConfig.SpeedSource]); u8x8.printf("%s\n", WiFi.localIP().toString().c_str()); } + + // Refresh the OLED display with the updated content u8x8.refreshDisplay(); } #endif +/** + * @brief Processes the button input and performs corresponding actions based on button state and timing. + * + * This function handles the button input, detecting button presses and executing actions based on + * predefined time delays. Actions include toggling WiFi, starting purge, toggling operating modes, + * and displaying feedback through LEDs. The function utilizes an enumeration to track button actions + * and manages the timing for different actions. + */ void Button_Process() { - + // Time delays for different button actions #define BUTTON_ACTION_DELAY_TOGGLEMODE 500 #define BUTTON_ACTION_DELAY_PURGE 3500 #define BUTTON_ACTION_DELAY_WIFI 6500 #define BUTTON_ACTION_DELAY_NOTHING 9500 + // Enumeration to represent button actions typedef enum buttonAction_e { BTN_INACTIVE, @@ -484,15 +646,18 @@ void Button_Process() BTN_STARTPURGE } buttonAction_t; + // Static variables to track button state and timing static uint32_t buttonTimestamp = 0; static buttonAction_t buttonAction = BTN_INACTIVE; + // Check if button is pressed (LOW) if (digitalRead(GPIO_BUTTON) == LOW) { - + // Update button timestamp on the first button press if (buttonTimestamp == 0) buttonTimestamp = millis(); + // Check and execute actions based on predefined time delays if (buttonTimestamp + BUTTON_ACTION_DELAY_NOTHING < millis()) { LED_Process(1, COLOR_WARM_WHITE); @@ -515,8 +680,9 @@ void Button_Process() buttonAction = BTN_TOGGLEMODE; } } - else + else // Button is released { + // Execute corresponding actions based on the detected button action if (buttonAction != BTN_INACTIVE) { switch (buttonAction) @@ -544,6 +710,7 @@ void Button_Process() globals.systemStatus = sysStat_Normal; globals.resumeStatus = sysStat_Normal; break; + default: break; } @@ -555,28 +722,49 @@ void Button_Process() Debug_pushMessage("Nothing or invalid\n"); break; } + + // Display feedback through LEDs LED_Process(2); } + + // Reset button state and timestamp buttonAction = BTN_INACTIVE; buttonTimestamp = 0; } } +/** + * @brief Toggles the WiFi functionality based on the current status. + * + * This function manages the WiFi state, either turning it off or starting it as an Access Point (AP), + * depending on the current mode. If the WiFi is turned off, it can be started in AP mode with the + * device name and password configured. Additionally, it may stop certain operations related to WiFi + * maintenance or display debug messages based on the defined features. + * + * @param shutdown Flag indicating whether the system is in a shutdown state. + */ void toggleWiFiAP(bool shutdown) { + // Check if WiFi is currently active if (WiFi.getMode() != WIFI_OFF) { + // Turn off WiFi WiFi.mode(WIFI_OFF); Debug_pushMessage("WiFi turned off\n"); + + // Stop WiFi maintenance connection ticker if enabled #ifdef FEATURE_ENABLE_WIFI_CLIENT WiFiMaintainConnectionTicker.stop(); #endif } else { + // Start WiFi in Access Point (AP) mode WiFi.mode(WIFI_AP); WiFi.softAPConfig(IPAddress(WIFI_AP_IP_GW), IPAddress(WIFI_AP_IP_GW), IPAddress(255, 255, 255, 0)); WiFi.softAP(globals.DeviceName, QUOTE(WIFI_AP_PASSWORD)); + + // Stop WiFi maintenance connection ticker if enabled and display debug messages #ifdef FEATURE_ENABLE_WIFI_CLIENT WiFiMaintainConnectionTicker.stop(); Debug_pushMessage("WiFi AP started, stopped Maintain-Timer\n"); @@ -586,19 +774,34 @@ void toggleWiFiAP(bool shutdown) } } +/** + * @brief Performs necessary tasks before shutting down and optionally restarts the ESP. + * + * This function initiates a system shutdown, performing tasks such as storing configuration + * and persistence data to EEPROM before shutting down. If a restart is requested, the ESP + * will be restarted; otherwise, the system will enter an indefinite loop. + * + * @param restart Flag indicating whether to restart the ESP after shutdown (default: false). + */ void SystemShutdown(bool restart) { static uint32_t shutdown_delay = 0; + // Initialize shutdown delay on the first call if (shutdown_delay == 0) { shutdown_delay = millis() + SHUTDOWN_DELAY_MS; Serial.printf("Shutdown requested - Restarting in %d seconds\n", SHUTDOWN_DELAY_MS / 1000); } + + // Check if the shutdown delay has elapsed if (shutdown_delay < millis()) { + // Store configuration and persistence data to EEPROM StoreConfig_EEPROM(); StorePersistence_EEPROM(); + + // Perform restart if requested, otherwise enter an indefinite loop if (restart) ESP.restart(); else @@ -607,6 +810,15 @@ void SystemShutdown(bool restart) } } +/** + * @brief Processes the impulses from the wheel speed sensor and converts them into traveled distance. + * + * This function takes the pulse count from the wheel speed sensor and converts it into distance + * traveled in millimeters. The conversion is based on the configured parameters such as the number + * of pulses per revolution and the distance traveled per revolution. + * + * @return The calculated distance traveled in millimeters. + */ uint32_t Process_Impulse_WheelSpeed() { uint32_t add_milimeters = 0;