HelixScreen supports the Snapmaker U1 toolchanger as an alternative touchscreen UI. The U1 runs Klipper with Moonraker on a Rockchip ARM64 SoC, and HelixScreen can replace the stock display interface when deployed via SSH.
The U1 is a 4-toolhead color printer. Each head has its own nozzle, extruder, heater, and filament sensor. Tool changes take approximately 5 seconds with no purging required.
The U1 does not use the standard viesturz/klipper-toolchanger module. Instead, it uses native multi-extruder with custom Klipper extensions. Extruders are named extruder, extruder1, extruder2, extruder3 with custom state fields (park_pin, active_pin, activating_move, state). HelixScreen has a dedicated AmsBackendSnapmaker that tracks tool state, RFID filament data, and supports tool switching via T0–T3 gcodes.
HelixScreen needs exactly one thing from the firmware: SSH access (to deploy and to install its boot hook). Both stock and community firmware can provide it — HelixScreen does not require PAXX.
Stock Snapmaker firmware (1.2+) ships the dropbear SSH server. It is disabled by default and gated behind the printer’s root/developer-access mode: /etc/init.d/S50dropbear exits early unless custom_misc vertype reports dbg. Snapmaker added a user-facing Root access option in firmware V1.2.0; enabling it (or flashing debug mode via custom_misc gen-debug, which persists across upgrades) starts dropbear with the standard root / lava accounts, password snapmaker. That is the exact SSH path HelixScreen uses — stock firmware is supported.
PAXX Extended Firmware is repackaged stock firmware plus an overlay of patches. It removes the dropbear debug-mode gate (SSH on by default) and bundles extras HelixScreen does not use — Tailscale, OctoEverywhere, WebRTC camera, a /firmware-config/ web UI, RFID filament write-back, etc. It is the turnkey option if you’d rather not enable stock root access yourself, but it is not a HelixScreen requirement.
Firmware
SSH
Status
Boot launcher HelixScreen hooks
Stock 1.2+
dropbear, enabled via Root access / debug mode
Supported (autostart newly added, see caveat)
No display init script exists; HelixScreen hooks S99input-event-daemon (the only boot-glob launcher present on stock).
Stock-firmware caveat: deploy, SSH, WiFi-credential reuse, and display takeover (chmod -x /usr/bin/gui) all rely on the base rootfs, which is byte-identical between stock and PAXX — so they work on stock. The stock boot-time autostart (the S99input-event-daemon hook) is newly added and not yet verified on a stock device (development hardware runs PAXX). The hook is additive and idempotent, so it is a no-op on PAXX; see How HelixScreen takes over the display.
The only PAXX-specific endpoint HelixScreen ever calls is /printer/filament_detect/set (RFID write-back); on stock it returns 404 and HelixScreen degrades gracefully (filament edits persist in HelixScreen’s own store instead of mirroring back to firmware).
The U1 root filesystem is a read-only SquashFS with a writable OverlayFS upper on /oem. /etc/init.d/S01aoverlayfs wipes that upper on every boot unless /oem/.debug exists, so the installer touches /oem/.debug to make its changes persist. (This overlay/.debug mechanism is byte-identical across firmware 1.2/1.3/1.4.)
To own the display and auto-start at boot, the installer:
Hooks a boot-time launcher — installs a HelixScreen delegate into whichever boot-glob init scripts ship in the firmware’s read-only SquashFS, each preserved as *.stock for the helix-not-installed fallback and for uninstall:
PAXX 1.2 / 1.3 → /etc/init.d/S99screen (the stock display launcher); delegate is helix-instead-of-stock-UI.
PAXX 1.4 → /etc/init.d/S99fb-http (S99screen was removed); delegate is helix-instead-of-stock-UI.
Stock firmware → /etc/init.d/S99input-event-daemon. Stock ships no display launcher in /etc/init.d (the stock UI is started by a supervisor binary), so there is nothing UI-shaped to hook. S99input-event-daemon is the one squashfs-resident, late-running script present on stock; the delegate preserves its function (runs the saved .stock to keep input-event-daemon going) and then starts HelixScreen. Because helixscreen.init start is idempotent, this same hook is harmless on PAXX (where an earlier launcher already started HelixScreen).
Disables the stock UI binary itself with chmod -x /usr/bin/gui (launcher-independent belt-and-suspenders so nothing can re-grab the framebuffer/DRM, regardless of which launcher or supervisor starts it). The uninstaller restores the exec bit.
Both changes live in the persistent overlay upper and survive reboot via /oem/.debug. A firmware upgrade re-flashes the rootfs and removes /oem/.debug, so HelixScreen must be reinstalled after any firmware update (stock or PAXX).
CRITICAL — the boot-glob trap that dictates which script we hook. busybox init runs /etc/init.d/rcSfrom the read-only SquashFS and expands its for i in /etc/init.d/S??* boot loop once, beforeS01aoverlayfs does its pivot_root onto the .debug overlay. So the list of script names is frozen from the SquashFS; a script created only in the overlay upper (not present in the SquashFS) is not in that frozen glob → it never runs at boot (only at shutdown, via rcK, once the overlay is active — a boot/shutdown asymmetry). This is why an installer-created /etc/init.d/S99screen does not autostart on PAXX 1.4 or stock (neither ships S99screen in its SquashFS). The fix is to delegate from a script that does ship in the SquashFS and runs afterS01aoverlayfs (so rcS executes its overlay copy, post-pivot): S99fb-http on PAXX 1.4, S99input-event-daemon on stock. Each hook is conditional ([ -f ]) and idempotent, so installing all of them is safe across every firmware variant.
# Build the Docker toolchain (first time only — cached after)
makesnapmaker-u1-docker
The Docker image (docker/Dockerfile.snapmaker-u1) is based on Debian Trixie with crossbuild-essential-arm64. It uses Debian’s aarch64-linux-gnu toolchain with static linking for a self-contained binary.
Stock firmware (1.2+): enable the printer’s Root access option (added in V1.2.0), or flash persistent debug mode (custom_misc gen-debug). This starts dropbear.
PAXX Extended Firmware: SSH is on by default. Download from paxx12-snapmaker-u1/SnapmakerU1-Extended-Firmware, flash via USB (FAT32, .bin in root). To toggle SSH explicitly: curl -X POST http://<printer-ip>/firmware-config/api/settings/ssh/true.
SSH access verified — connect as root (works on both):
The installer auto-detects the U1 platform, downloads the correct aarch64 binary from the release CDN, deploys platform hooks, and starts HelixScreen. Re-run to upgrade.
DRM keepalive: a background process opens /dev/dri/card0 to prevent CRTC teardown
The stock UI process (gui) is killed, and the installer disables its binary (chmod -x /usr/bin/gui) so no launcher can relaunch it. lmd (the camera/timelapse supervisor) is left running — killing it would break timelapse.
HelixScreen starts as DRM master with double-buffered page flipping
The DRM keepalive process exits once HelixScreen has the DRM device open
The first-run wizard appears (language selection, printer connection setup)
To restore the stock Snapmaker touchscreen UI, run the uninstaller — it re-enables the stock UI binary (/usr/bin/gui) and restores the stock S99screen launcher (firmware 1.3) or removes the HelixScreen-created one (firmware 1.4):
Terminal window
sshroot@<printer-ip>"curl -sSL https://raw.githubusercontent.com/prestonbrown/helixscreen/main/scripts/install.sh | sh -s -- --uninstall; reboot"
A bare rm -rf /userdata/helixscreen is no longer sufficient. The installer disables the stock UI binary (chmod -x /usr/bin/gui) so neither firmware’s launcher can start it; removing HelixScreen without re-enabling the binary leaves a black screen. If you can’t run the uninstaller, revert manually:
HelixScreen can be deployed to the U1 without modifying the read-only base firmware — all changes live in the writable overlay and are fully reversible.
Deploy via make deploy-snapmaker-u1 SNAPMAKER_U1_HOST=<ip>
The installer disables the stock UI binary (chmod -x /usr/bin/gui) and installs a HelixScreen launcher at /etc/init.d/S99screen (in the writable overlay); HelixScreen starts on /dev/fb0. lmd (camera/timelapse supervisor) keeps running.
To revert: run the uninstaller (re-enables /usr/bin/gui and restores the launcher), or manually chmod +x /usr/bin/gui && rm -rf /userdata/helixscreen, then reboot. The stock UI binary is on the read-only SquashFS rootfs and is only disabled, never deleted — but note that the init-script changes and the binary’s exec bit are modified (in the reversible overlay), so a plain reboot alone will not bring the stock UI back.
Package HelixScreen as an overlay in paxx12’s Extended Firmware build system:
Add a HelixScreen overlay that deploys the binary and init script
Build a custom firmware .bin with the overlay included
Flash via USB like any firmware update
To revert: Flash stock firmware (or Extended Firmware without the HelixScreen overlay) via USB. A/B firmware slots ensure the previous firmware is preserved.
HelixScreen uses the DRM backend for double-buffered page flipping on /dev/dri/card0 (rockchipdrmfb). The 480x320 MCU panel runs on a DPI/RGB parallel interface via the Rockchip VOP2 display controller.
The CRTC keepalive problem: The stock UI (/usr/bin/gui) holds DRM master. When gui exits, the kernel’s VOP2 driver calls vop2_crtc_atomic_disable, permanently disabling the display until reboot. The MCU panel driver only creates modes during the initial boot sequence — once the CRTC is disabled, there’s no way to re-enable it.
The solution: The platform hooks (config/platform/hooks-snapmaker-u1.sh) spawn a background process that holds /dev/dri/card0 open before killing gui. This prevents the kernel from tearing down the CRTC when gui exits. HelixScreen then opens the DRM device itself and becomes DRM master. The keepalive process detects that HelixScreen has the device open and exits — but the CRTC stays active because HelixScreen now holds the fd.
Critical implementation notes:
The keepalive MUST be a background subshell ((exec 3>/dev/dri/card0; ...) &), not a shell fd (exec 7>). Shell fds die when the init script exits, but background processes survive.
The keepalive polls /proc/*/fd until it sees helix-screen with /dev/dri/card0 open, then exits.
HELIX_DRM_DEVICE=/dev/dri/card0 is set in platform_pre_start() to skip auto-detection.
No libinput is needed — touch input uses evdev directly.
Filesystem note: /opt/ is an overlay filesystem wiped on reboot. All persistent data lives on /userdata/ (ext4, 28GB). /home/lava/ is also part of the overlay and is NOT persistent.
Touch input is provided by a TLSC6x capacitive controller (tlsc6x_touch) on /dev/input/event0. HelixScreen auto-detects this device and uses multitouch (MT) axis ranges (0-480, 0-320). No touch calibration is required — the capacitive controller is factory-calibrated.
HelixScreen auto-detects the Snapmaker U1 using 17 heuristics from config/printer_database.json:
Heuristic
Confidence
Description
fm175xx_reader object
99
FM175xx RFID reader — definitive U1 signature
FILAMENT_DT_UPDATE macro
95
RFID filament detection macro (extended firmware)
FILAMENT_DT_QUERY macro
95
RFID filament query macro (extended firmware)
Hostname u1
90
Hostname contains “u1”
Hostname snapmaker
85
Hostname contains “snapmaker”
tmc2240 object
60
TMC2240 stepper driver presence
CoreXY kinematics
40
CoreXY motion system
Cartesian kinematics
20
Cartesian motion system
(+9 additional heuristics)
various
Tool state, extruder naming, custom macros, motion parameters, etc.
No manual printer configuration is needed in most cases. The FM175xx RFID reader is the strongest signal — it is unique to the U1 and provides near-certain identification.
When the U1 is detected, the printer database record provides these metadata fields:
Field
Value
probe_type
eddy_current
toolhead_style
snapmaker_u1
preset
snapmaker_u1
z_offset_calibration_strategy
probe_calibrate
The snapmaker_u1 preset causes the first-run wizard to auto-skip hardware steps that do not apply to the U1 (e.g., probe wiring, toolhead identification).
HelixScreen uses the snapmaker_u1 print start profile (config/print_start_profiles/snapmaker_u1.json) to track progress through the startup sequence. The profile uses weighted progress mode with these phases:
Homing (10%)
Bed heating (20%)
Nozzle heating (20%)
Z tilt adjust (15%)
Bed mesh calibration (15%)
Nozzle cleaning (10%)
Purging (10%)
The progress bar updates as each phase completes, so you can see exactly where your printer is in its startup routine.
The U1’s 480x320 display uses the TINY layout preset. This is the smallest resolution HelixScreen supports, and several UI panels have known layout issues at this size. See the 480x320 UI Audit for a panel-by-panel breakdown. Key issues:
Navbar icons clipped at screen edges
Controls panel labels overlapping, z-offset value wrapping
Print select list view fundamentally broken at this size
Numeric keypad overlay too tall, bottom rows cut off
Filament panel cards pushed off-screen
These are resolution-specific issues, not Snapmaker-specific. Any 480x320 device benefits from the same fixes.
480x320 UI needs work — Multiple panels have layout issues at this resolution (see above).
SSH access required — deployment needs SSH. Stock firmware (1.2+) provides it via the Root access option / debug mode; the community Extended Firmware enables it by default. Either works — PAXX is not required. (Stock boot-time autostart is newly added and pending verification on stock hardware; see Firmware Requirements.)
Auto-start requires /oem/.debug — The overlay filesystem is wiped on boot unless /oem/.debug exists. This flag must be created once during installation to persist the boot-launcher hook (see How HelixScreen takes over the display).
WiFi management — Stopping unisrv (stock UI) does not affect WiFi — the U1 uses standard wpa_supplicant managed by the OS. HelixScreen has its own WiFi manager with wpa_supplicant support.
Remote screen (“gui” webcam) not yet wired up — The firmware ships a screen-capture daemon (/usr/local/bin/fb-http.py, PNG snapshot on 127.0.0.1:8092, reads /dev/fb0 via mmap), an nginx /screen/ route (/etc/nginx/fluidd.d/remote-screen.conf), and a [webcam gui] Moonraker slot. Two gaps make it show “No Signal — maybe not enabled?”: (1) the daemon has no service unit and isn’t running, and (2) HelixScreen renders into its own DRM dumb buffer and never writes /dev/fb0, so even when the daemon runs it serves a stale boot-leftover frame. Note /dev/fb0 is not unreadable under DRM — it’s a separate, idle buffer decoupled from scanout (bench-confirmed: a magenta write to fb0 was served by the daemon while the panel kept showing HelixScreen untouched). See Future Work for the fix.
Two benign Moonraker warnings on buildroot — After install, Mainsail/Fluidd surface “Unable to find DBus PolKit Interface” (Moonraker’s always-loaded machine component on a no-PolKit OS) and “Unable to initialize System Update Provider for distribution: buildroot” (Moonraker’s update_manager initializes a system/OS package provider by default, which can’t detect apt/PackageKit on buildroot). The PolKit one is not ours — it’s inherent to Moonraker on buildroot and re-surfaces because our installer restarts Moonraker. The system-update one is triggered by us adding [update_manager helixscreen] (loading the component pulls in the default system provider); it can be silenced with a top-level [update_manager] / enable_system_updates: False, which doesn’t affect HelixScreen’s own one-click updater. Both are harmless. Same condition applies to K1/K2 (also buildroot).
Serve the HelixScreen UI as the [webcam gui] feed so it shows in Mainsail/Fluidd. Validated approach (bench-tested 2026-06-14): the “fb0 mailbox.” Don’t build an in-process server — reuse the firmware’s existing capture daemon (fb-http.py on :8092, nginx /screen/, [webcam gui] slot). The daemon mmaps and reads /dev/fb0, PNG-encodes on demand (md5/ETag-cached, so a static screen is nearly free), and does its own work on the device’s CPU — we add no server and no encoder.
Our only job is to keep /dev/fb0 current. fb0 is a separate buffer decoupled from our DRM scanout (proven: writing magenta to fb0 was served by the daemon while the panel stayed on HelixScreen). Implementation:
Mirror frames into fb0. Open /dev/fb0 once, mmap MAP_SHARED|PROT_WRITE. In the existing flush hook (DisplayManager::install_color_transform_hook(), src/application/display_manager.cpp), copy rendered (dirty) regions into fb0 — BGRA, stride 1920 (480×320×4), throttled to a few fps to match the daemon’s poll rate. One main-thread memcpy, no encode. We write post-rotation pixels, so the remote view matches the panel automatically.
Enable the daemon. It currently has no service unit and isn’t running. Ship a systemd unit (or installer step) that starts python3 /usr/local/bin/fb-http.py, and ensure the [webcam gui] Moonraker entry points at /screen/snapshot.
Caveats: occasional tearing if we write mid-poll (acceptable for a remote view, or double-buffer); throttle the mirror cadence to bound CPU. Bonus — remote control:fb-http.py also injects touch to /dev/input/event0 via its /touch endpoint, so this gets remote control nearly for free — pending a check that HelixScreen reads event0 (separate follow-up). PNG snapshot is poll-based, not a continuous MJPEG stream.
The AmsBackendSnapmaker backend parses RFID data from filament_detect.info when the RFID reader is enabled. With the RFID reader disabled (default on Extended Firmware via disable-rfid-reader.cfg), all RFID fields return "NONE" and print_task_config is the authoritative filament data source.
The U1 supports an extruder_map_table with 32 virtual slots mapped to 4 physical extruders. This could enable more advanced filament management workflows.
We welcome additional testers with Snapmaker U1 hardware — especially anyone running STOCK firmware (with Root access enabled), since stock boot-time autostart is implemented but not yet verified on a stock device:
Enable SSH — stock firmware: turn on the Root access option in printer settings; or install the Extended Firmware (SSH on by default, then curl -X POST http://<ip>/firmware-config/api/settings/ssh/true if needed)
Install via one-liner (easiest): curl -sSL https://releases.helixscreen.org/install.sh | sh
Stock testers: after install, reboot and confirm HelixScreen comes back up on its own (this exercises the S99input-event-daemon boot hook) — please report success/failure.
Or build from source: make snapmaker-u1-docker then make deploy-snapmaker-u1-fg SNAPMAKER_U1_HOST=<ip>
Report: Does the wizard appear? Does touch work? Can you connect to Moonraker? Do tool changes work?