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 in91604c2. 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>
4.3 KiB
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]onlevelboard:PD0). - 4 filament channels, each a direct-drive extruder on its own head — there is no
feed hub;
manual_stepper gear_stepperis the tool LOCK motor (see47-filament-load-recovered.md). Presence sensorsfd_ex0..3, motion sensorsfm_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 expects20-klipper-fork.md— fork delta: custom commands, theTninterception25-app-vs-klipper-ownership.md— which side owns which behaviour, and what is ported30-toolchange.md— dock/grab/release sequences, sensors, mounted-tool state40-offsets.md— where per-unit numbers live; per-tool offsets; the absolute print Z offset45-tool-offset-calibration.md— the Klipper port: storage layout, commands, guards46-offset-calibration-recovered.md— the app's calibration sequence it was ported from47-filament-load-recovered.md/48-filament-load-port.md— load/unload/purge49-runout-recovered.md— runout and clog handling (ported:ff-runout.cfg)50-print-lifecycle.md— start/pause/resume/cancel/complete, address-verified50a-nozzle-clean-recovered.md/50b-nozzle-clean-port.md— the pre-print nozzle clean60-background.md— filament system, calibration flows, config keys (background context)70-error-codes.md— full E-code table (behavioral spec)