Skip to content

Overview

The firmware is structured to allow modular enabling and configuration of various hardware components and features. The key files involved in this process are config.h, features.h, and PHApp.cpp.

This file is the central place for defining hardware-specific configurations.

  • Component IDs: An enum COMPONENT_KEY defines unique identifiers for various software components (e.g., COMPONENT_KEY_RELAY_0, COMPONENT_KEY_PID_0).
  • Platform Detection: Preprocessor directives (#if defined(...)) detect the target hardware platform (e.g., PLATFORM_PORTENTA_H7_M7, PLATFORM_ESP32) and include platform-specific headers.
  • Debugging Switches: Macros control debugging features, like serial logging (DISABLE_SERIAL_LOGGING).
  • App Features: Macros like HAS_MODBUS_REGISTER_DESCRIPTIONS enable or disable specific application-level functionalities.
  • Status Feedback Settings: Pins for status LEDs (warning, error) and blink intervals are defined here (e.g., STATUS_WARNING_PIN, STATUS_ERROR_PIN).
  • Serial Port Settings: Baud rate and command parsing intervals for serial communication are set (e.g., SERIAL_BAUD_RATE).
  • Auxiliary Settings (GPIO Pins):
    • For specific platforms like ESP32, GPIO pins for relays, analog inputs, and other peripherals are mapped using macros (e.g., GPIO_PIN_CH1, AUX_RELAY_0).
    • Analog input parameters like POT_RAW_MAX_VALUE and POT_SCALED_MAX_VALUE are defined.
  • Component-Specific Configurations:
    • Analog Level Switch: Parameters like ALS_0_NUM_LEVELS, ALS_0_ADC_STEP, and Modbus addresses are defined.
    • LED Feedback: Data pin, pixel count, and Modbus addresses for LED strips.
    • Joystick: Pins for UP, DOWN, LEFT, RIGHT directions.
  • Network Configuration:
    • Filename for network settings (NETWORK_CONFIG_FILENAME).
    • Static IP addresses, gateway, subnet, and DNS servers for Wi-Fi STA mode.
    • SSID and password for the Wi-Fi network to connect to.
    • Configuration for AP_STA mode, including AP SSID, password, and IP settings, if ENABLE_AP_STA is defined.
  • Main Feature Switches: A set of #define directives (e.g., ENABLE_WIFI, ENABLE_WEBSERVER, ENABLE_MODBUS_TCP, ENABLE_RS485, ENABLE_PID) globally enables or disables major firmware modules. These switches are crucial as they control conditional compilation throughout the codebase.

This header file acts as an intermediary that includes necessary component headers based on the feature flags defined in config.h.

  • It includes config.h to get the feature flags.
  • For each feature enabled in config.h (e.g., ENABLE_STATUS, ENABLE_RELAYS, ENABLE_JOYSTICK), it uses preprocessor directives (#ifdef) to include the corresponding header file for that component (e.g., components/StatusLight.h, components/Relay.h, components/Joystick.h).
  • This ensures that only the code for enabled features is compiled, reducing the final firmware size and resource usage.

This is the main application file where the enabled features and components are instantiated and brought to life.

  • Includes: It includes PHApp.h, config.h, config_adv.h, config-modbus.h, and features.h. The inclusion of features.h ensures that all necessary component classes are declared.
  • Component Instantiation:
    • Inside the PHApp::setup() method, components are created using new.
    • The instantiation is often guarded by the same #ifdef preprocessor directives used in config.h and features.h. For example:
      #ifdef ENABLE_RELAYS
      #ifdef AUX_RELAY_0
      ADD_RELAY(0, AUX_RELAY_0, COMPONENT_KEY_RELAY_0, MB_ADDR_AUX_5); // Macro expands to new Relay(...)
      #endif
      #endif
    • Pin numbers and other configuration values defined in config.h (e.g., AUX_RELAY_0, PIN_JOYSTICK_UP) are passed as arguments to the component constructors.
    • Component keys (e.g., COMPONENT_KEY_RELAY_0) from config.h are used to identify components.
    • Modbus addresses (e.g., MB_ADDR_AUX_5) from config-modbus.h are also passed during instantiation.
  • Component Registration:
    • After instantiation, components are typically added to a components vector (e.g., components.push_back(relay_0);).
    • They might also be registered with other manager components, like a Bridge for serial communication or a ModbusTCP manager.
  • Conditional Logic:
    • The PHApp::setup() and PHApp::loop() methods, as well as other parts of PHApp.cpp, use #ifdef directives extensively to conditionally compile code related to specific features. This ensures that only relevant logic for enabled features is executed.
    • For example, Modbus setup, web server route registration, and specific component interactions are all conditionally compiled.
  1. config.h: Define what hardware is present (pins) and which high-level features should be globally enabled/disabled. This file sets the stage with macros.
  2. features.h: Based on the macros from config.h, this file includes the necessary header files for the classes that implement those features. It acts as a selective include manager.
  3. PHApp.cpp: This file takes the enabled features (whose classes are now declared via features.h) and the configurations (pins, IDs from config.h) to create actual instances of these components and integrate them into the application’s lifecycle (setup(), loop()).

This layered approach allows for a highly configurable and modular firmware, where features can be easily toggled and adapted to different hardware configurations without extensive code changes in the core application logic.