Files
firmware/docs/notes/00-overview.md
T
Oleksandr ShyshatskyiandClaude Opus 5 d05565284d Sections E, F, G: wrong values, stale claims, overclaims
E -- values and counts. The START_PRINT prologue has no M400 and an idle
timeout of 864000, not 1800000. The nozzle-clean temperature comes from the
material table FIRST, so NOZZLE=240 with no per-tool temp cleans at 220 --
documented backwards before. TOOLS is the paired 0:220,2:240 form. The wipe Z
is the raw eddy frame, not the homed one. The runout M117 strings are
"T<n> clog" / "T<n> out of filament", not E-codes. Grab-verify raises
E0051+tool, not E0143. Docks are at X~297; 250/280 are staging waypoints. The
grab sequence is documented in the order _grab actually emits it. ff_print
exposes seven status fields, not nine, and never emits TOOLS=. Package sizes
reconciled against the real artifacts (62MB built, ~93MB stock, ~370MB of CI
assets, ~60s not 90s). testing.md's sample output block matched no header the
code prints, so it is replaced with the real ones; its pytest row listed two
of six suites.

F -- stale claims. _FF_PREFLIGHT is not "missing". SDCARD_SET_CHANNEL is not
still issued (764af2a). The app and Moonraker do not coexist; the app is gone.
TOOLCHANGE_STATUS has nothing to compare against since the JSON reader was
removed. The JSON is re-imported every boot until a nozzle is saved, not once.
The 23-check render harness was deleted in 91604c2. PURGE now wipes by
default. 50-print-lifecycle.md gained the section on how the sequences are
actually entered now -- [ff_print], not the slicer. The dead "profiles"
concept is gone from three files, one of which printed it on every replica run.

G -- overclaims. The README no longer says a stock reflash puts the printer
back "exactly as it was": it says what is restored and what survives inert,
which is what test-recovery actually asserts. The random ssh password is
conditional on ROOT_PW_HASH being unset. verify.sh no longer warns "ssh will
not start" on every build for a dropbear we deliberately do not ship -- the
check now reads the way round it means. case-install.sh's read-only block says
it asserts nothing. An uncalibrated tool contributes z_adjust, not zero, in
three operator-facing places. offset_base does not cancel out in X/Y. The
safe-moves file's Z50 promise is scoped to its own lines, with the implicit
prepare's G1 Z10 spelled out.

48 passed, 5 skipped.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-24 19:48:43 +03:00

4.3 KiB
Raw Blame History

firmwareExe analysis — overview

Analyzed binary: firmwareExe (20.9 MB, ELF 32-bit MIPS32r2, Ingenic XBurst2 SoC, Linux 3.10.14, not stripped — full C++ symbols). Machine identifies itself as "Creator 5 Pro", cloud backend api.voxelshare.com.

The single most important finding

The printer already runs Klipper. firmwareExe is NOT the motion firmware — it is the LVGL touchscreen UI + orchestration daemon. It:

  • starts Klipper with /usr/prog/klipper/start.sh &
  • talks to Klipper's native API socket at /tmp/uds (stock webhooks JSON: gcode/script, objects/query, objects/subscribe, …)
  • implements everything "smart" (toolchange orchestration, print lifecycle, filament runout auto-swap, calibration wizards, cloud/camera/LAN APIs) app-side, by sending G-code strings.

The Klipper fork itself ships no START/END/PAUSE/RESUME/CANCEL macros and no toolchange motion code — a print started from Mainsail/Moonraker gets none of that behaviour unless something re-provides it. That something is this repo: ff_toolchange.py + the config/macros.

System architecture

firmwareExe (touchscreen app)
 ├─ LVGL UI on /dev/fb0 + touch /dev/input/event2
 ├─ KlipperAPI ──/tmp/uds──► Klipper fork (/usr/prog/klipper)
 │                            ├─ mcu           main board: X/Y/Z, bed
 │                            ├─ eboard        /dev/ttyS5 carriage extruder driver
 │                            ├─ eheaterboard  /dev/ttyS4 4 hotend heaters + 24V
 │                            └─ levelboard    /dev/ttyS7 fixed under-bed cylinder
 ├─ DryingService ──/dev/ttyS3──► filament drying box (own MCU, not Klipper)
 ├─ OrcaServer / MQTT cloud / camera
 └─ /usr/data/firmwareRes/config/*.json — per-unit calibration + state

Printer facts

  • 4-tool toolchanger: docked heads T0–T3 at X≈297 (250/280 are the staging and approach waypoints, not the docks), picked up by the X carriage with a lock motor (current sensing via temperature_sensor motor_value).
  • Bed ~250×250, 10×10 bed mesh from the carriage eddy ([probe], eboard:PG0). Nozzle XY/Z offset calibration uses a different sensor: the fixed inductive cylinder under the bed ([e_stop X/Y/Z] on levelboard:PD0).
  • 4 filament channels, each a direct-drive extruder on its own head — there is no feed hub; manual_stepper gear_stepper is the tool LOCK motor (see 47-filament-load-recovered.md). Presence sensors fd_ex0..3, motion sensors fm_ex0..3.
  • Chamber heater + 4 fans + LED, front/top door switches.

Method

The binary is not stripped, so targeted questions are answered by reading symbols and disassembling straight from the file (capstone), rather than a full Ghidra project — Ghidra's auto-analysis wrongly marked the logging helpers noreturn and truncated ~916 functions (29k bogus CALL_RETURN overrides), so its decompile of exactly the interesting CommMgr methods was misleading until repaired. Addresses cited in these notes are verified against the live binary.

Notes map

Files ending -recovered are reconstructions of the stock app's behaviour; the matching -port note says what this repo actually shipped.

  • 10-hardware.md — MCUs, serial ports, Klipper objects the UI expects
  • 20-klipper-fork.md — fork delta: custom commands, the Tn interception
  • 25-app-vs-klipper-ownership.md — which side owns which behaviour, and what is ported
  • 30-toolchange.md — dock/grab/release sequences, sensors, mounted-tool state
  • 40-offsets.md — where per-unit numbers live; per-tool offsets; the absolute print Z offset
  • 45-tool-offset-calibration.md — the Klipper port: storage layout, commands, guards
  • 46-offset-calibration-recovered.md — the app's calibration sequence it was ported from
  • 47-filament-load-recovered.md / 48-filament-load-port.md — load/unload/purge
  • 49-runout-recovered.md — runout and clog handling (ported: ff-runout.cfg)
  • 50-print-lifecycle.md — start/pause/resume/cancel/complete, address-verified
  • 50a-nozzle-clean-recovered.md / 50b-nozzle-clean-port.md — the pre-print nozzle clean
  • 60-background.md — filament system, calibration flows, config keys (background context)
  • 70-error-codes.md — full E-code table (behavioral spec)