Why Fixo (and not a runtime-configurable alternative)

OctoMY™ has one hardware controller today — Fixo — that compiles your robot's actuator/sensor configuration into purpose-built firmware via embedded LLVM/Clang. Earlier releases also shipped a runtime-configurable path called Fluxo (originally ArduMY) and a Servotor32 binding. Both were retired in 2026 in favour of the single Fixo path. This page explains the reasoning so the choice doesn't look arbitrary.

Did You Know?

The name Fixo comes from Latin fixus — fixed, fastened. The retired runtime-config sibling was named Fluxo (Latin fluxus, flowing), reflecting the static/dynamic split. After Fluxo's removal the duality is gone, but the Fixo name stuck because it accurately describes how the firmware is generated.


What Fixo does differently

Fixo's job is to take a FixoPreset (board + actuators + sensors + lobes) and produce a purpose-built firmware binary for that exact configuration. The C++ optimizer inlines every actuator type, pin number, and sensor descriptor as a compile-time constant; dead code paths are eliminated; the resulting binary contains zero runtime configuration overhead.

Agent
  │
  ├─ FirmwareGenerator : preset → C++ source
  ├─ FirmwareCompiler  : LLVM/Clang → AVR ELF + native .so
  ├─ FirmwareFlasher   : ELF → MCU flash
  │
  └──serial──▶ Arduino  (purpose-built firmware)
                 │
                 ├─ All actuator types are compile-time constants
                 ├─ All pin assignments are compile-time constants
                 ├─ Lobe logic is compiled in
                 └─ Reports sensor values via numex

Configuration changes require a rebuild + reflash — but with the embedded LLVM toolchain that takes seconds, not the minutes a traditional cross-compiler workflow would. The flash cycle itself is around five seconds for a typical binary.


Why we removed the runtime-configurable path

Fluxo (the previous dynamic-config path) worked but carried inherent costs on the constrained MCUs OctoMY targets:

Fixo flips all of those: every value is a compile-time constant, the optimizer collapses unused branches, and the generated source can host whatever C++ a lobe author wants to write.

Note

The runtime-configurable path made sense in a world where compiling C++ on a developer machine was a multi-step toolchain dance. Once we vendored LLVM/Clang into the Agent itself, that ergonomic cost disappeared: the user clicks Build and the firmware lands on the board seconds later. With the cost gone, the runtime-config drawbacks weren't worth carrying.


What's still shared

A lot of what was once described as "shared between Fixo and Fluxo" survived the removal:

Component Where it lives now
Numex wire protocol libnumex/ — the value/command protocol talks to whatever firmware is running
Board definitions libboard/ — pin capabilities, flash sizes
Flash protocols libfirmware/ — STK500v1/v2/AVR109 flashing
Actuator and sensor types libfixo/ — now part of the Fixo type registries

A robot still uses exactly one controller. There's just no longer a "controller type" decision to make: it's Fixo.


Hardware support

Feature Status
Actuator control (servo, motor, stepper, relay) Stable
Sensor reading (digital, analog, encoder, limit-switch, tachometer) Stable
Identity lobe (passthrough) Stable
Wheeled / tracked drive lobes Stable
Hexapod gait, limb placement, hovering Stable (templates ship in the studio)
AVR backend (ATmega328P, ATmega2560) Stable
Native backend (host-side testing via dlopen) Stable infrastructure; native compilation pipeline lands per spec
Stanza switching with conflict-disabling Stable (Phase 7)
Live sensor readback on Remote Stable (Phase 7)