Figures¶
Every figure on this site is drawn by a Python module from facts extracted from the code, so it is rebuilt,
not redrawn, when the code changes. CI runs hardfoc-docs figures --check and fails when a
committed figure no longer matches the code. Each figure below lists the files it is drawn from.
Vortex V1: buses and chips¶
Figure description and sources
The ESP32-C6 on the left runs all the software. Each arrow to the right is one bus or signal, labelled with the GPIOs it uses: SPI2 to the TMC9660 motor controller and the AS5047U encoder (plus two external chip selects), a UART that is the TMC9660's default host link, I2C to the PCAL95555 I/O expander and the BNO08x IMU, TWAI to the CAN transceiver, and one data line to the WS2812 status LED. The PCAL95555 drives the TMC9660 control lines (driver enable, reset, wake, SPI mux) and the IMU's boot and reset lines, and reads their fault and interrupt outputs. The layout is drawn by hand; every GPIO number, expander bit, chip select, SPI mode and I2C address is read from the functional pin map and the comms manager, so a pin change rebuilds this figure.
Drawn from: lib/core/hf-core-drivers/internal/hf-pincfg/src/hf_functional_pin_config_vortex_v1.hpp HF_FUNCTIONAL_GPIO_PIN_LIST; lib/managers/CommChannelsManager.h SpiDeviceId; lib/managers/CommChannelsManager.cpp add_builtin_device; figure module docs/diagrams/figures/board-overview.py.
Figure module: docs/diagrams/figures/board-overview.py
Drawn from:
HF_FUNCTIONAL_GPIO_PIN_LISTinlib/core/hf-core-drivers/internal/hf-pincfg/src/hf_functional_pin_config_vortex_v1.hppSpiDeviceIdinlib/managers/CommChannelsManager.hadd_builtin_deviceinlib/managers/CommChannelsManager.cpp
Vortex V1 HAL, layer by layer¶
Figure description and sources
From top to bottom, each layer only calls the one under it. Your application asks the facade singleton for the managers. The managers (one per board function) are MCU-free: they own the hf-core handlers, which wrap one chip driver each, and they get every bus, MCU pin, NVS namespace and the status LED from the board binding. The binding is the only HAL code that names an ESP32 type; it constructs the ESP32 implementations of the interface classes, which sit on ESP-IDF. Drivers talk to hardware only through those interface classes. Every name in a band is read from the code: the managers from the facade's member references, the binding's classes from its #include lines, the handlers, drivers and interface classes from the managers' and handlers' #include lines.
Drawn from: lib/api/Vortex.h Vortex (manager references); lib/managers #includes; lib/core/handlers #includes; lib/managers/bsp_bind/esp32c6 #includes; figure module docs/diagrams/figures/hal-layers.py.
Figure module: docs/diagrams/figures/hal-layers.py
Drawn from:
Vortex (manager references)inlib/api/Vortex.h#includesinlib/managers#includesinlib/core/handlers#includesinlib/managers/bsp_bind/esp32c6
Vortex::EnsureInitialized()¶
Figure description and sources
Left to right, then the second row. The facade initialises the managers one at a time, in the order of the calls in its init function. The first group is required: if any of them fails, EnsureInitialized() returns false and the application should not continue. The second group is best effort: a failure there is logged as a warning, the manager stays unavailable and the system reports itself as degraded, so a bench with only some chips fitted still comes up. The order and the required / best-effort split are read from the init function, which returns false only in the required branches.
Drawn from: lib/api/Vortex.cpp Vortex::InitializeAllComponents; figure module docs/diagrams/figures/init-order.py.
Figure module: docs/diagrams/figures/init-order.py
Drawn from:
Vortex::InitializeAllComponentsinlib/api/Vortex.cpp
Managers, handlers and drivers¶
Figure description and sources
Managers on the left, hf-core handlers in the middle, chip drivers on the right. An arrow means "includes and uses": a manager owns or borrows the handler it points at, and each handler wraps exactly one driver. Several managers share the TMC9660 handler, because that one chip provides motor control, GPIO, ADC channels and a temperature sensor; MotorController owns it and the others reach it through MotorController. LedManager uses its driver directly, without a handler. Managers with no arrow (communication buses, NVS) talk to the interface wrap only.
Drawn from: lib/managers #includes; lib/core/handlers #includes; figure module docs/diagrams/figures/manager-dependencies.py.
Figure module: docs/diagrams/figures/manager-dependencies.py
Drawn from:
#includesinlib/managers#includesinlib/core/handlers