diff --git a/docs/BRINGUP.md b/docs/BRINGUP.md index a75baaf..aace69f 100644 --- a/docs/BRINGUP.md +++ b/docs/BRINGUP.md @@ -355,7 +355,7 @@ factory 2.6.0-2228 session; measured numbers in the facts bank). alike: the retrace is sized to `cnc/max_backtrack` and the lead follows it, so a pause with little history behind it shortens both rather than failing. GRBL mode uses feed hold / cycle start, so a resumed GRBL cut picks up where - the deceleration ended (item 12). A pause is not a cancel: the latch + the deceleration ended (item 11). A pause is not a cancel: the latch stays unlocked and the window open across it. There is no resume dwell: the safing chain re-arms ~216 ms before the first step (facts bank). - **`lid_policy = hold`** selects stock grblHAL door behavior instead (park in @@ -1102,67 +1102,15 @@ is committed. Open items only. Anything closed is in `CAMPAIGN-LOG.md`. 1. **Limit-switch homing.** The planned second homing method (`$22` stays 0 - until it lands); printable brackets are in `3d-models/`. Also: calibrate - `gfcloud_home_x/y` against a jog to a known reference if the factory corner - offset matters. + until it lands). 2. **Cameras.** **First light on an 8 MP (OV8856) machine**: the whole path is written but nothing has run on one, and only that hardware can answer whether the 2-lane RAW8 full-resolution mode locks the D-PHY at 720 Mbps/lane and what exposure/gain the sensor wants; the details, the reachable-mode reasoning and the factory fallback configuration are in the headers of kernel patches 0011-0013 (`meta-glowforge-bsp`, - `recipes-kernel/linux/`). Lens shading (OmniVision LENC) is not a gap: the factory - rootfs carries `load_cam_regs.sh`, a loader that writes a register file - into the OV8856 driver's `regs` sysfs attribute (OV8858 `0x58xx` - addresses remapped to `0x59xx`), but nothing calls it; the app - references `/usr/bin/apply_cam_regs.sh`, which is not on the rootfs; the - OV5648 driver has no `regs` attribute; and this machine's `/data` holds - no register file. No shipped machine applies a per-unit shading table, - so ForgeFIRM owes none. Finally the deferred emulator - homing-image smoke, now that the emulator can be pointed at live snapshots. -3. **Cloud mode.** A print is no longer capped by the ring: the client holds - the compressed body, fills the ring before the button, and tops it up as it - plays, with the body bounded by `pulse_reject_threshold_bytes` because - memory is what that costs. A feed that wedges is caught by progress rather - than by ring depth (a healthy feeder keeps the ring brim-full, so depth - only falls an hour after the feed died): thirty seconds of no progress with - room in the ring stops the job cleanly and retraces, and it resumes if the - feed moves again. A running print also reports itself to the app again, on - the carrier a factory-session capture settled: the `type:"progress"` frame - that is the periodic settings report, every 30 s and at every phase change, - divided by the job's own length rather than by the kernel byte counter that - climbs all job long under a live feed. The `cloud.*` acceptance tests - cover all of it on the bench, a print longer than the ring fed from the - live service included, and the app has been watched reporting a print's - progress. `gfcloud.init` autostart with `controller_mode = cloud` is - validated on a flashed image, and the lid flash follows the action's - `LCfl`. What is left is tracked in - `python3-gfhardware/forgefirm-app/docs/CLOUD.md` "Outstanding items" and - is short: whether the service accepts an 8 MP machine's larger images (no - HD machine has been on the bench). The pulse header's envelope is - settled: every tag the service fills in is applied, passed through as a - limit that can only tighten, refused on, logged or declared ignored with - its reason (`CLOUD.md` "The pulse header"), and the gates behind it live - in the cooling engine so they hold in GRBL mode too. The memory guards - (`pulse_reject_threshold_bytes`, 128 MiB of compressed body) stay - reasoned rather than measured, by decision: nothing the service sends - comes near them, and every job logs the body and program sizes the - guards are reasoned from. The lifecycle keys (`CFrh`, `CCwp`, `CCrp`, - `CCup`) are settled as inert, in the factory too, so the configured - warm-up and rest on the factory's measured timings are the model, and - `CCbp`/`CCbt` are report-only tags that cannot appear in a header. The - four actions the service has never been seen to send were read out of - the factory binary: `user_image` is a lid capture and is implemented; - `update_check`, `factory_reset` and `head_firmware_update` each hand off - to a program this machine does not have (a factory updater, a reset - script, a head firmware push), so each is answered on the wire and none - is performed, and `focus` is ignored exactly as the factory ignores it. - Declined outright: SPKI pinning, emulator full-session parity, and the - factory's ten-event pause phase machine. Not inducible from the bench: - the cancel-with-a-rejected-`settings`-action case, a malformed frame - (needs a MITM), a body past the memory guard (the service has no such job - to send), and a wedged feed (a healthy machine will not stall on request). -4. **Shared machine services — remaining polish.** None of it blocking: + `recipes-kernel/linux/`). +3. **Shared machine services — remaining polish.** None of it blocking: - **Diagnostics as engine modes.** The flow tools still drive the thermal hardware themselves while the engine suspends its writes; the check parameters are already shared (`cool.h`), so what remains is folding the @@ -1178,26 +1126,26 @@ Open items only. Anything closed is in `CAMPAIGN-LOG.md`. `ensure_engine` `popen()`s should move out of the HTTP callback so a slow media-ctl cannot stall the request thread. Changing the MHD start flags touches the streaming model, so this wants a bench slot of its own. -5. **Physical-evidence negatives still open.** A present head answering I²C +4. **Physical-evidence negatives still open.** A present head answering I²C badly (the K-11 runtime case) and a failed head capture leaving the measure laser off — both need the head connected and a fault injected. Opportunistic: `STATE_FAULT` recovery via `enable` the next time a DRV8825 fault line actually trips. -6. **Debug-kernel checks.** Module load/unload under `CONFIG_DEBUG_MUTEXES` +5. **Debug-kernel checks.** Module load/unload under `CONFIG_DEBUG_MUTEXES` and a forced `-EPROBE_DEFER` unwind still need a debug kernel build. Both drills cycle what the rail policy avoids: a module unload powers the 40 V rail off (a stepper driver can come out of the power-up unserviceable), and a forced defer needs the 40 V regulator or the SDMA device unbound under the module's probe. This is a bench slot with the rail-cycle gamble accepted, not a quick check. -7. **Wi-Fi SDIO CRC watch.** The uSDHC pads now carry the factory-exact values +6. **Wi-Fi SDIO CRC watch.** The uSDHC pads now carry the factory-exact values and ship in every image. Watch `dmesg | grep -c "sdio .* failed"` across sessions (baseline: 1 event in 49 min of uptime). Effect if one lands mid-job: a 1–2 s sender stall — a cut-quality nuisance, never a safety matter. Only if it still recurs, cap the bus with `max-frequency = <25000000>` on `&usdhc1` (halves Wi-Fi throughput — last resort; the factory ran 50 MHz on these pads). -8. **Release acceptance follow-through.** The campaign is the release gate +7. **Release acceptance follow-through.** The campaign is the release gate and runs as designed: dev image `20260824230512`, 45 of 45 from nothing, 36 of them unattended with the bench actuator in the loop, release authorized (the export is on the board at `/data/forgetest/export/`). @@ -1210,17 +1158,19 @@ Open items only. Anything closed is in `CAMPAIGN-LOG.md`. into transport and transfer helpers would take websocket-transport changes off the offline tests (a gfutilities refactor, not a map). Tools that genuinely need a second host (LAN flood, remote auth probes) - stay host-side by design, and the registry marks them so. The first - release is item 9. -9. **Publish.** The first release: `releases/v/acceptance.json` + stay host-side by design, and the registry marks them so. The deferred + emulator homing-image smoke is tool work here too, now that the + emulator can be pointed at live snapshots. The first + release is item 8. +8. **Publish.** The first release: `releases/v/acceptance.json` from the authorized export, `scripts/release.sh`, the kas flip and the first GitHub release, per the site (Developers, "Release flow"), once ready to publish. Repoint the core submodule to upstream if the `step_us_min` sizing fix merges. -10. **Update system Phase 5 — recovery refresh.** The remaining phase of +9. **Update system Phase 5 — recovery refresh.** The remaining phase of `docs/UPDATE-SYSTEM.md` (a refreshed recovery image in boot0); Phases 0–4 are done. -11. **Head-IRQ source validation — beam-emission hypothesis (exploratory, not +10. **Head-IRQ source validation — beam-emission hypothesis (exploratory, not gating).** The EV_SW `head` bit (GPIO3_22, factory pad HEAD_IRQ) is the head MCU's attention line — idle LOW with a healthy head, pulsing on head reboot, floating to the SoC pull-up with no head — so the raw level is not a @@ -1236,7 +1186,7 @@ Open items only. Anything closed is in `CAMPAIGN-LOG.md`. log EV_SW head-bit edges plus `head/beam_detect_digital|_analog` while firing. -12. **Gapless pause and resume in GRBL mode (planned).** A pause leaves a mark +11. **Gapless pause and resume in GRBL mode (planned).** A pause leaves a mark in the cut. With laser mode on, the core stops the beam at the start of the hold (`disable_laser_during_hold`, on by default), so the head travels the whole deceleration dark, and the resume re-accelerates from a standstill at @@ -1270,7 +1220,7 @@ Open items only. Anything closed is in `CAMPAIGN-LOG.md`. line does to it, and how it composes with the armed window's disarm grace across a long hold. -13. **Head crash and rail-contact detector (planned).** The head +12. **Head crash and rail-contact detector (planned).** The head accelerometer is the motion-liveness probe and nothing more; the factory runs two tiers off the same sensor (a per-axis alert that pauses, a per-axis abort), and its thresholds arrive in every pulse @@ -1282,7 +1232,7 @@ Open items only. Anything closed is in `CAMPAIGN-LOG.md`. are established. A pause on contact, on the factory's shape, would be the first use. -14. **A sender change while a job runs: discussion.** Today a sender that +13. **A sender change while a job runs: discussion.** Today a sender that disconnects mid-job leaves the motion running to the end of what the controller holds, with the window closed and fire suppressed (the consent belonged to the displaced session), so the job finishes dark @@ -1299,9 +1249,9 @@ Open items only. Anything closed is in `CAMPAIGN-LOG.md`. a hold parks the head over hot material with the assist air on the run profile, and the grace then closes the window in Hold as it does today; running on leaves a clean stop position but wastes the piece. Decide - with the gapless pause and resume item (12), which owns the resume + with the gapless pause and resume item (11), which owns the resume mechanics. -15. **The flow check while the tube is lit.** The arm-time heater check +14. **The flow check while the tube is lit.** The arm-time heater check starts at the session open, so with a prompt press the tube is lit for most of its window, and a lit CW window adds about 1.5 C to the rise (0.5 C at 45 % density) against a 1.6 C margin; on top of that the @@ -1334,7 +1284,7 @@ Open items only. Anything closed is in `CAMPAIGN-LOG.md`. remains; a scope on the two sensor lines during a cut is the next instrument. It sits inside the ceiling's 2 C hysteresis and the flow check reads means, so it is a measurement item, not a gate item. -16. **Laser power-good: what the line means.** `cnc/laser_pgood` and its +15. **Laser power-good: what the line means.** `cnc/laser_pgood` and its sampled count are defined in the UAPI (active low, one sample every ~3.9 ms), the facts bank records that the sampled count reads 0 through real cutting, and the cooling engine warns @@ -1346,7 +1296,7 @@ Open items only. Anything closed is in `CAMPAIGN-LOG.md`. scope against `hv_current` through an armed cut, its meaning written into the facts bank and the UAPI, and then either a warning that means something or no warning. -17. **Initial commissioning: measure and set the machine's own numbers +16. **Initial commissioning: measure and set the machine's own numbers methodically.** Every tunable that was measured on the bench machine and shipped as a default varies from machine to machine: the flow check's bands and `cool_flow_rise`, the tube's heat coefficients @@ -1382,8 +1332,8 @@ covers the warm-up hold), the supply temperature window (the service sends the whole ADC range and the factory binds it to nothing; the supply is watched per job instead), the head, lid, interconnect and fused temperature ceilings (no sensor at those locations; the chassis is watched per job), the -head accelerometer thresholds (item 13), the lid IR thresholds (the fire +head accelerometer thresholds (item 12), the lid IR thresholds (the fire watch runs on local knobs; the header values stay ignored), the HV current caps (the sampled emission witness covers the idle case, and HV current is ranged per job), the thermal report upload conditions and the -pump flag. Beam detect stays with item 11. +pump flag. Beam detect stays with item 10. diff --git a/docs/CAMPAIGN-LOG.md b/docs/CAMPAIGN-LOG.md index 4172c6d..6850baa 100644 --- a/docs/CAMPAIGN-LOG.md +++ b/docs/CAMPAIGN-LOG.md @@ -6487,6 +6487,58 @@ to 17. prior for this redesign and nothing else: the cloud client declares them ignored, and the watch stays disabled until it is lamp-aware. +### Cloud mode (item 3), closed 2026-08-31 + +Closed as a status recitation: the content is present-state fact that +lives in `CLOUD.md` (the envelope, the guards, the actions, the +declined set), and the one open question, whether the service accepts +an 8 MP machine's larger images, stays in `CLOUD.md` "Outstanding +items" and rides the 8 MP first light (the cameras item). Items 4 and +up move down one. + +3. **Cloud mode.** A print is no longer capped by the ring: the client holds + the compressed body, fills the ring before the button, and tops it up as it + plays, with the body bounded by `pulse_reject_threshold_bytes` because + memory is what that costs. A feed that wedges is caught by progress rather + than by ring depth (a healthy feeder keeps the ring brim-full, so depth + only falls an hour after the feed died): thirty seconds of no progress with + room in the ring stops the job cleanly and retraces, and it resumes if the + feed moves again. A running print also reports itself to the app again, on + the carrier a factory-session capture settled: the `type:"progress"` frame + that is the periodic settings report, every 30 s and at every phase change, + divided by the job's own length rather than by the kernel byte counter that + climbs all job long under a live feed. The `cloud.*` acceptance tests + cover all of it on the bench, a print longer than the ring fed from the + live service included, and the app has been watched reporting a print's + progress. `gfcloud.init` autostart with `controller_mode = cloud` is + validated on a flashed image, and the lid flash follows the action's + `LCfl`. What is left is tracked in + `python3-gfhardware/forgefirm-app/docs/CLOUD.md` "Outstanding items" and + is short: whether the service accepts an 8 MP machine's larger images (no + HD machine has been on the bench). The pulse header's envelope is + settled: every tag the service fills in is applied, passed through as a + limit that can only tighten, refused on, logged or declared ignored with + its reason (`CLOUD.md` "The pulse header"), and the gates behind it live + in the cooling engine so they hold in GRBL mode too. The memory guards + (`pulse_reject_threshold_bytes`, 128 MiB of compressed body) stay + reasoned rather than measured, by decision: nothing the service sends + comes near them, and every job logs the body and program sizes the + guards are reasoned from. The lifecycle keys (`CFrh`, `CCwp`, `CCrp`, + `CCup`) are settled as inert, in the factory too, so the configured + warm-up and rest on the factory's measured timings are the model, and + `CCbp`/`CCbt` are report-only tags that cannot appear in a header. The + four actions the service has never been seen to send were read out of + the factory binary: `user_image` is a lid capture and is implemented; + `update_check`, `factory_reset` and `head_firmware_update` each hand off + to a program this machine does not have (a factory updater, a reset + script, a head firmware push), so each is answered on the wire and none + is performed, and `focus` is ignored exactly as the factory ignores it. + Declined outright: SPKI pinning, emulator full-session parity, and the + factory's ten-event pause phase machine. Not inducible from the bench: + the cancel-with-a-rejected-`settings`-action case, a malformed frame + (needs a MITM), a body past the memory guard (the service has no such job + to send), and a wedged feed (a healthy machine will not stall on request). + ## Reference notes ### Head-IRQ source validation — the beam-emission hypothesis