Reference for the Fixo controller, which compiles robot hardware configuration into purpose-built firmware via embedded LLVM/Clang.
Design Note
Fixo firmware contains zero runtime configuration overhead: no config parser, no dynamic arrays, no type dispatch. Every actuator type, pin number, and sensor configuration is a compile-time constant. The optimizer eliminates all dead code paths, producing the smallest and fastest possible binary for the exact hardware configuration.
Fixo is the controller in OctoMY™. It bakes the entire hardware configuration into firmware as C++ template parameters and compiles it via embedded LLVM/Clang. The earlier runtime-config path (Fluxo / ArduMY) and Servotor32 binding were retired in 2026.
The trade-off is a rebuild+reflash cycle on every configuration change — acceptable because LLVM compilation takes seconds and the flash cycle is approximately 5 seconds for a typical binary.
See Why Fixo for the design rationale, and the Fixo data model for the type vocabulary used below (FixoPreset, FixoStanza, FixoActuatorType, etc.).
| Board | MCU | Flash | SRAM | Pins | PWM |
|---|---|---|---|---|---|
| Arduino Uno | ATmega328P | 32 KB | 2 KB | 14 digital, 6 analog | 6 |
| Arduino Mega 2560 | ATmega2560 | 256 KB | 8 KB | 54 digital, 16 analog | 15 |
| Backend | Output | Purpose |
|---|---|---|
| AVR | ELF binary, flashed to MCU | Production deployment on physical Arduino boards |
| Harness | Native x64 shared library | Host-side testing with virtual actuator/sensor UI — no physical hardware required |
The harness backend compiles the same template code but links against Qt stubs instead of AVR register code. Virtual servos, motors, and sensors appear as widgets in the controller UI.
Fixo supports the same actuator types as Actuators:
| Type | Description | Pins required |
|---|---|---|
| RC Servo | PWM-driven position servo | 1 (PWM) |
| DC Motor | Speed-controlled motor with direction | 2 (PWM + direction) |
| Stepper Motor | Step/direction stepper driver | 2 (step + direction) |
| Relay | On/off digital output | 1 (digital) |
Each actuator can optionally declare additional pins for limit switches, incremental encoders, tachometers, and position feedback sensors.
| Type | Description | Pins | Resolution |
|---|---|---|---|
| Digital Input | Polled digital pin | 1 | 1-bit |
| Analog Input | ADC reading | 1 | 10-bit (configurable) |
| Encoder | Quadrature incremental encoder | 2 (A + B) | Count-based |
| Counter | Pulse counter (IRQ-driven) | 1 | Count-based |
| Limit Switch | Active-low digital input | 1 | 1-bit |
| Tachometer | RPM from pulse frequency | 1 | Frequency-based |
Fixo compiles lobe logic directly into the firmware as C++ template code. Built-in lobes:
| Lobe | Description |
|---|---|
identity |
Passthrough — actuator values map 1:1 to outputs |
wheeled |
Differential-drive controller; outputs left_motor / right_motor |
tracked |
Tracked-vehicle controller; outputs left_track / right_track |
legged_gait |
Multi-leg gait engine (used by the hexapod template) |
hovering, limb_placement, trim, blink_led |
Specialised controllers; see Lobes reference |
Each FixoLobeType carries a placement capability — board-only, native-only, or both — that determines whether the lobe runs in the firmware (compiled into the AVR ELF) or on the node (loaded from the matched native .so via dlopen). See the Lobes reference for placement details and the per-lobe input/output port lists.
FixoController declares the following capability flags:
| Capability | Description |
|---|---|
CAP_ADD_ACTUATORS |
Add actuators at configuration time |
CAP_REMOVE_ACTUATORS |
Remove actuators at configuration time |
CAP_ACTUATOR_TYPE_SELECTION |
Choose from RC Servo, DC Motor, Stepper, Relay |
CAP_PIN_ASSIGNMENT |
Assign physical pins to actuators |
CAP_RANGE_CONFIG |
Configure actuator value ranges |
CAP_LIMIT_SWITCHES |
Attach limit switch sensors |
CAP_POSITION_FEEDBACK |
Attach position feedback sensors |
CAP_INCREMENTAL_ENCODER |
Attach quadrature encoder sensors |
CAP_TACHOMETER |
Attach tachometer sensors |
CAP_GEAR_RATIO |
Configure mechanical gear ratios |
CAP_CONTINUOUS_MODE |
Support continuous-rotation servos |
CAP_LINEAR_MODE |
Support linear actuators |
FixoRuntime (see the FixoRuntime reference) drives the build / inject / start lifecycle. Triggers:
| Trigger | Description |
|---|---|
| Manual | User clicks Build, then Inject, then Start |
| Auto-build | Preemptive background compile on preset change (500 ms debounce) |
| Autonomous (future) | Runtime decides it is safe to rebuild and reflash |
FirmwareGenerator::generateFromPreset() synthesises C++ source from the active FixoPreset.FixoBuildManager invokes the embedded LLVM/Clang to produce both an AVR ELF (board-side) and a native .so (node-side).FirmwareSizeInfo validates that the AVR ELF fits in the target board's flash.FixoFirmwareCache content-addresses the compiled artefacts by BLAKE3 hash so unchanged presets don't recompile.FirmwareFlasher writes the AVR ELF to the board via stk500v2 over serial.FirmwareRuntime dlopens the native .so (when present) into the Agent process; the runtime opens the numex serial link and starts ticking the firmware.The preset editor exposes a live size bar driven by FirmwareSizeInfo:
| Colour | Meaning |
|---|---|
| Default | Usage below 80 % of available flash |
| Orange | Usage between 80 % and 100 % |
| Red | Firmware exceeds available flash — will not fit |
Fixo configuration lives in fixo.json files, not in the legacy fixo/* agent settings. See the Fixo Books reference for how presets, types, and templates are stored, and the fixo.json schema reference for the file format.
A typical layout:
<personality>/fixo/
presets/
rc-car.fixo.json
hexy-explorer.fixo.json
actuator-types/ # custom types (built-ins live in libfixo's qrc)
sensor-types/
lobe-types/
stanza-templates/
preset-templates/
Files are discovered recursively by FixoLibrary::scan(); routing by fixoType field places each into the matching Fixo*Book.
Fixo's UI lives in the Fixo Studio activity (see the Fixo Studio reference). The Studio is the entry point for:
The retired multi-screen "BoardSelect → Configure → Build → Dashboard" widget has been replaced by the Studio + a per-preset FixoRuntime view. The Studio runs on Hub, Agent, or Remote (each node can author and share presets); only "set as active runtime" is Agent-specific.
| Component | Library | Path |
|---|---|---|
FixoController |
libfixo | fixo/controller/FixoController.hpp |
FirmwareGenerator |
libfixo | fixo/controller/FirmwareGenerator.hpp |
FixoBuildManager |
libfixo | fixo/controller/FixoBuildManager.hpp |
FirmwareSizeInfo |
libfixo | fixo/controller/FirmwareSizeInfo.hpp |
FixoRuntime |
libfixo | fixo/runtime/FixoRuntime.hpp |
FirmwareRuntime |
libfixo | fixo/runtime/FirmwareRuntime.hpp |
FixoLibrary and Books |
libfixo | fixo/library/Fixo*.hpp |
| Studio activities | libfixo | fixo/studio/Fixo*.hpp |
| Type editors | libfixo | fixo/type/Fixo*Editor*.hpp |
| Preset editor | libfixo | fixo/studio/FixoPresetEditorActivity.hpp |
| Control widgets | libfixo | fixo/widget/Fixo*.hpp |