motion.jog-roundtrip gets a check after its hold/resume segment, with the head at the start and the machine at rest: a 60 mm +X G1 at F3000, and a ^X 0.3 s after the kernel starts to play it. At a soft reset during motion the grblHAL driver stops the kernel with its ramp, reads the position back from the kernel's step counters, and keeps the core's reference. No other catalog test sends a ^X while the head moves, and the null-sink harness cannot read real counters: its residue is zero by construction. The check fails when: - the controller is not in Alarm within 2 s of the ^X, or is Idle with no alarm (the move had ended before the ^X); - cnc/state does not leave running within 1.0 s, or leaves it for a state other than idle, or cnc/underruns or cnc/faults change across the check; - the kernel did not decelerate: over the run's last 25 to 50 ms, the bytes played (the position record, polled at 5 ms) are more than 70% of cnc/step_freq; - the ring holds bytes after the reset; - after $X, MPos X in steps ($100) and the kernel's X count differ by more than one step, or Y or Z moved; - the homed mask changes, or the sender gets a [MSG:] line that the position cannot be read back; - the jog back by the MPos distance leaves the kernel's X counter more than one step from its start. The head is jogged back before these judgments, so a failure of one of them leaves the head at the start. The ramp witness is the tail rate because of the arithmetic. At the stop the ring holds about 110 ms of ticks: the 200 ms queue and the 10 ms lead, less the 100 ms that the core's alarm hold plays. The ramp to the kernel's 900 Hz floor uses 112.6 ms of ticks, in every mode, because the ramp scales with the tick. So the run ends at the floor or runs out of data part of the way down the ramp, and the steps that never played can be zero. A minimum of unplayed steps in the driver's read-back log line, the bytes played after the ^X, and the time to leave running cannot tell the ramp from a run-out with a 20% margin. The log line is also an INFO line, which the log level setting can remove. The tail rate is 21% to 56% of the tick for 90 to 110 ms of queue at the stop, and 100% for a run-out. The other readings and the log line go to the evidence. The homed mask comes from the controller port's state record (forgectrl /motion/state): $# prints [HOME:...:mask] only with $22 on, and the driver's default is off. Before the reset the mask must hold the Z bit (the lens hold), because a mask without it cannot show a dropped reference. The test also requires kernel.k1-k2, the kernel's controlled stop on the SoC. The title and the description say what the test proves now. est_min stays 3. Proof: compile and pyflakes 4.0.3 give no message on suite/motion.py and no undefined name in forgetest or tests. forgetest unit tests, python3 -B -m unittest discover -s tests -p test_<name>.py, in a private PID namespace: test_manifest.py 39 OK, test_queue.py 15 OK, test_campaign.py 13 OK. Coverage lint on the tree manifest from scripts/manifest-from-tree.py (python3 -B -m forgetest.coverage --manifest ../tree-manifest.json --enforce): 0 uncovered, 0 empty, 0 host-tested row problems, 43 tests. A host dry run of the whole test against the null-sink build of grblHAL-glowforge f3158d3: the head accelerometer, the kernel's state and bytes-played counter, and forgectrl are stand-ins; the step counters are the steps of the shipped stream; /motion/state is the controller's own control port. With a model kernel that ramps from the controller's cnc/stop write, the test passes: tail 23% of the tick, MPos X 3496.1 steps against 3496, mask 4 kept, the read-back log line found, the X counter back at its start, drift 0.000 mm. With a model kernel that plays its queue to the end at the tick, the ramp check fails at 100%. Against the null-sink build of the parent (eb8eb61), the check fails on the mask (4 -> 0) and on the read-back (MPos X 3483.1 steps against 3482). The real counters, the ramp, and the machine's timing are read on the machine only. Acceptance: the change is inside the test's own function, so the shared text of suite/motion.py does not change. The fingerprint of motion.jog-roundtrip moves, and no other test's: of the implementation hashes of the 43 catalog tests, before and after, only that one differs. The new check runs on the bench in the next campaign as part of motion.jog-roundtrip.
OpenGlow / ForgeFIRM firmware for Glowforge
BETA
ForgeFIRM is in beta. Every release below 0.1.0 is a beta release. It's stable, but you may still hit the occasional bug, and expect frequent updates. Upgrade whenever a newer release is available, and report what you find on the community forum.
Open firmware for Glowforge brand CNC lasers. ForgeFIRM replaces the cloud-dependent factory software on the stock control board, with no hardware modification, and gives the machine a local controller, a local web control panel, and a standard Grbl interface. The factory cloud experience stays available as an option.
This repository is the base of the build and of the release: the
meta-forgefirm Yocto layer, the kas configuration, the image recipes, the
install and release scripts, the acceptance tool (forgetest/), the bench
tools (scripts/bench/), the bench actuator firmware (fixture/), and the
release artifacts (releases/).
Start here
https://docs.forgefirm.org/ is the documentation, and the source of truth for every fact about the machine and the firmware.
| Read this first | Safety |
| Put it on a machine | Installation |
| Use it | Usage, LightBurn |
| How the machine works | Technical |
| How ForgeFIRM works with it | ForgeFIRM internals |
| Build, test, release | Developers |
| Downloads | Releases |
| Questions | Community forum |
Build
kas build kas/forgefirm-glowforge.yml
Build covers the host setup, the two images, the source variant and the debug kernel. Release flow covers the pins, the push order and the signing pipeline.
Test
cd forgetest && python3 -m unittest discover -s tests -v
The acceptance catalog that gates a release, and the bench tools, are on Acceptance and The bench.
Contributing
AGENTS.md carries the rules for this repository and for the project: safety ordering, proof before done, the push order, and the writing rules. They apply to human contributors too, and Contribute is the same set on the site.
What this costs
Nothing. ForgeFIRM is free in both senses, under MIT and GPL licenses. There is no paid tier, no license key, no subscription and no Pro edition. If someone offers to sell it to you, the licenses allow it, but what you take home is their build rather than this one: get it from the source.
Safety
These machines contain a CO2 laser: it burns, blinds, and starts fires. Never defeat the lid switches or the interlock. Never leave a running job unattended. Keep a fire extinguisher within reach. Read Safety before you cut your first job, and Regulatory and legal before you install.
This is experimental software. Use of it could seriously maim or kill you or others, and it may void your warranty. Use it at your own risk.
Glowforge is a trademark of Glowforge, Inc. This project is not affiliated with, authorized by, or endorsed by Glowforge, Inc.