mirror of
https://github.com/openglow-org/forgefirm.git
synced 2026-09-28 01:01:12 -07:00
Retire next-work item 1: the gap question is answered from the chain
The button latch is SET by lid-open or the SoC lock and RESET by the button only; the charge-pump watchdog feeds HV_ENABLE, not the latch. A kernel-run gap inside an armed job drops HV_ENABLE and leaves the latch alone, and the next run has HV_ENABLE back before its first step. No keepalive. laser.emission-witness carries a G4 P2 between the second and third sides of its square and checks cnc/button_latch clear in every armed sample, HV_ENABLE dropped across the dwell and back with emission after it; the operator confirms all four sides. BRINGUP: item 1 removed, items 2 to 21 are now 1 to 20, the five cross-references follow, the flow-band sentence is in the facts bank. CAMPAIGN-LOG: the answer, the retired item, and the unattended set run green on the hot-deployed board (campaign c-20260831151846).
This commit is contained in:
+29
-32
@@ -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 16). A pause is not a cancel: the latch
|
||||
the deceleration ended (item 15). 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
|
||||
@@ -958,7 +958,10 @@ is committed.
|
||||
coolant thermistor conversion is the factory B-equation recovered from the
|
||||
v2.6.0 binary — derivation in `kernel-module-glowforge/UAPI.md`; the old
|
||||
UAPI "best guess" linear formula was 3–5 °C high and everything derived from
|
||||
it had to be re-derived.
|
||||
it had to be re-derived. The flow check's bands hold from 19 to 27 C, the
|
||||
loop heater's ceiling in a 20 C room, with the margin widening warm; above
|
||||
that only a running tube warms the loop, and the check takes the tube's
|
||||
share off.
|
||||
- **The four `pic/lid_ir_*` channels are first of all a photometer for the lid
|
||||
lamp.** Measured against `lid_led` (sysfs brightness, 0 to 1023): all four
|
||||
channels follow it as a straight line, 2 counts dark, 32 to 35 at 128, 54 to
|
||||
@@ -1096,13 +1099,7 @@ is committed.
|
||||
|
||||
Open items only. Anything closed is in `CAMPAIGN-LOG.md`.
|
||||
|
||||
1. **Laser commissioning leftovers.** Verify the hardware button latch persists
|
||||
across kernel-run gaps mid-job (if OK_2_FIRE drops between motion bursts, the
|
||||
fix is a stream keepalive across armed gaps). The flow check's bands
|
||||
hold from 19 to 27 C, the loop heater's ceiling in a 20 C room, with the
|
||||
margin widening warm; above that only a running tube warms the loop,
|
||||
and the check takes the tube's share off.
|
||||
2. **Low-temperature gates and warm-up (planned).** Two keys in the Cooling
|
||||
1. **Low-temperature gates and warm-up (planned).** Two keys in the Cooling
|
||||
card: `cool_temp_min` (hard floor, default ~5 °C, a fire gate) and
|
||||
`cool_temp_start` (warm-up gate, default ~16 °C) — a job starting below the
|
||||
gate holds in a factory-style warm-up phase with the loop heater on and
|
||||
@@ -1111,7 +1108,7 @@ Open items only. Anything closed is in `CAMPAIGN-LOG.md`.
|
||||
coolant. Sequencing: warm-up first, flow check after. Measured physics on
|
||||
this bench: 50 % duty warms the bulk ~0.5–0.8 °C/min and plateaus ~8–9 °C
|
||||
above ambient — the same unaided limit the factory has.
|
||||
3. **TEC handling (planned).** `thermal/tec_on` is a bare on/off output with no
|
||||
2. **TEC handling (planned).** `thermal/tec_on` is a bare on/off output with no
|
||||
readback, so presence cannot be detected: it becomes a `tec_present` user
|
||||
setting (Machine tab, default off; ForgeFIRM never drives `tec_on` unless
|
||||
set), which also covers retrofits. Operation when present: simple hysteresis
|
||||
@@ -1123,7 +1120,7 @@ Open items only. Anything closed is in `CAMPAIGN-LOG.md`.
|
||||
all is a spec-level claim (Glowforge ships it on the Pro; Basic/Plus use the
|
||||
same passive closed-loop cooling), not teardown-verified per unit — another
|
||||
reason it is a setting.
|
||||
4. **Fire watch (lid IR) redesign.** The gate stays disabled
|
||||
3. **Fire watch (lid IR) redesign.** The gate stays disabled
|
||||
(`cool_fire_ir_delta = 0`) until it is lamp-aware: the engine must own or
|
||||
observe the lamp level (suspend the watch and re-baseline for a few ticks
|
||||
after any `lid_led` change) and the threshold must be relative to the
|
||||
@@ -1146,11 +1143,11 @@ Open items only. Anything closed is in `CAMPAIGN-LOG.md`.
|
||||
cloud job carries. By decision those header thresholds (`IR??`) are the
|
||||
prior for this redesign and nothing else: the cloud client declares them
|
||||
ignored, and the watch stays disabled until it is lamp-aware.
|
||||
5. **Limit-switch homing.** The planned second homing method (`$22` stays 0
|
||||
4. **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.
|
||||
6. **Cameras.** **First light on an 8 MP (OV8856) machine**: the
|
||||
5. **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
|
||||
@@ -1165,7 +1162,7 @@ Open items only. Anything closed is in `CAMPAIGN-LOG.md`.
|
||||
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.
|
||||
7. **Cloud mode.** A print is no longer capped by the ring: the client holds
|
||||
6. **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
|
||||
@@ -1207,7 +1204,7 @@ Open items only. Anything closed is in `CAMPAIGN-LOG.md`.
|
||||
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).
|
||||
8. **Shared machine services — remaining polish.** None of it blocking:
|
||||
7. **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
|
||||
@@ -1223,26 +1220,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.
|
||||
9. **Physical-evidence negatives still open.** A present head answering I²C
|
||||
8. **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.
|
||||
10. **Debug-kernel checks.** Module load/unload under `CONFIG_DEBUG_MUTEXES`
|
||||
9. **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.
|
||||
11. **Wi-Fi SDIO CRC watch.** The uSDHC pads now carry the factory-exact values
|
||||
10. **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).
|
||||
12. **Release acceptance follow-through.** The campaign is the release gate
|
||||
11. **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/`).
|
||||
@@ -1256,16 +1253,16 @@ Open items only. Anything closed is in `CAMPAIGN-LOG.md`.
|
||||
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 13.
|
||||
13. **Publish.** The first release: `releases/v<version>/acceptance.json`
|
||||
release is item 12.
|
||||
12. **Publish.** The first release: `releases/v<version>/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.
|
||||
14. **Update system Phase 5 — recovery refresh.** The remaining phase of
|
||||
13. **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.
|
||||
15. **Head-IRQ source validation — beam-emission hypothesis (exploratory, not
|
||||
14. **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
|
||||
@@ -1281,7 +1278,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.
|
||||
|
||||
16. **Gapless pause and resume in GRBL mode (planned).** A pause leaves a mark
|
||||
15. **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
|
||||
@@ -1315,7 +1312,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.
|
||||
|
||||
17. **Head crash and rail-contact detector (planned).** The head
|
||||
16. **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
|
||||
@@ -1327,7 +1324,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.
|
||||
|
||||
18. **A sender change while a job runs: discussion.** Today a sender that
|
||||
17. **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
|
||||
@@ -1344,9 +1341,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 (16), which owns the resume
|
||||
with the gapless pause and resume item (15), which owns the resume
|
||||
mechanics.
|
||||
19. **The flow check while the tube is lit.** The arm-time heater check
|
||||
18. **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
|
||||
@@ -1379,7 +1376,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.
|
||||
20. **Laser power-good: what the line means.** `cnc/laser_pgood` and its
|
||||
19. **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
|
||||
@@ -1391,7 +1388,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.
|
||||
21. **Initial commissioning: measure and set the machine's own numbers
|
||||
20. **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
|
||||
@@ -1427,7 +1424,7 @@ 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 17), the lid IR thresholds (item 4), the
|
||||
head accelerometer thresholds (item 16), the lid IR thresholds (item 3), 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 15.
|
||||
pump flag. Beam detect stays with item 14.
|
||||
|
||||
@@ -4726,6 +4726,55 @@ does not carry, and the 5 MP driver has no way to take one. BRINGUP
|
||||
item 6 now says so, and the factory-slot session it asked for is not
|
||||
needed.
|
||||
|
||||
## 2026-08-31: the mid-job gap question, answered from the chain
|
||||
|
||||
Item 1 asked whether the hardware button latch persists across a
|
||||
kernel-run gap inside an armed job, with a stream keepalive as the fix if
|
||||
it did not. The safing chain answers it (`docs/SAFETY.md` section 2): the
|
||||
button latch is U23 latch 1, SET by lid-open OR the SoC lock (U32) and
|
||||
RESET by the physical button only. The charge-pump watchdog feeds
|
||||
HV_ENABLE, not the latch. A gap (a `G4` dwell, a hold, the end of a cycle
|
||||
before the next) drops HV_ENABLE 454 ms after the last pump pulse and
|
||||
leaves the latch as it was, while the driver keeps the SoC lock released
|
||||
through the armed window; on the next run HV_ENABLE is back within ~3 ms,
|
||||
~216 ms before the first step (the pads measurement of 2026-08-15). A
|
||||
planner starve is not a gap: the stream pads the ring dark and the run
|
||||
keeps playing. A keepalive would hold HV_ENABLE up while nothing is cut,
|
||||
the one state the watchdog exists to prevent, so none is built.
|
||||
|
||||
The one thing never watched on the bench, the latch readback through a
|
||||
lit-dwell-lit sequence, rides `laser.emission-witness` from now on: the
|
||||
square carries a `G4 P2` between its second and third sides, the sampler
|
||||
reads `cnc/button_latch` and `switches.hv_enable`, and the test checks
|
||||
the latch clear in every armed sample, HV_ENABLE dropped across the
|
||||
dwell and back with emission after it, and the operator confirms all
|
||||
four sides. It runs with the attended set. Item 1 is retired; its
|
||||
flow-band sentence is a fact and moved to the facts bank ("Cooling
|
||||
operating point").
|
||||
|
||||
## 2026-08-31: the unattended set on the hot-deployed board
|
||||
|
||||
The first unattended run of the day (campaign c-20260831143855) stopped
|
||||
on `cooling.aa-offset-calibrate`, the test's first campaign run ever,
|
||||
queued right after `cooling.flow-verify`: the loop was still mixing
|
||||
after the no-flow trial (19.6 C rise, the sensors 13.5 C apart), the
|
||||
tool's fixed 6 s settle let the trend into its first edge (+44.7 and
|
||||
+20.6 counts against 13 to 18 on the settled edges), and its spread
|
||||
check refused the result (35.5 counts against a limit of 8). Fix: the
|
||||
tool waits at the flow tools' stationary gate before its first edge
|
||||
(forgectrl 7dbb5e1) and the test gives it 540 s (forgefirm eb8935c).
|
||||
|
||||
By operator decision the fix went onto the board without an image:
|
||||
the pinned forgectrl built by bitbake (md5 7e1f28cc) and the suite
|
||||
file installed over ssh on dev 20260831141210, forgectrl and forgetest
|
||||
restarted. The test then passed alone (offset 15.0 counts, spread 6.0,
|
||||
edges 12.2 to 18.2), and the unattended queue of 20 ran green behind it
|
||||
in campaign c-20260831151846 (21 PASS, the 17 other unattended tests
|
||||
inherited from the morning run, one ABORTED record from a page start
|
||||
before the fix was in). The attended set is deferred by decision. The
|
||||
campaign that authorizes a release runs on the image that carries every
|
||||
fix, burned once.
|
||||
|
||||
## Superseded status notes
|
||||
|
||||
### Shared machine services — remaining polish, as listed 2026-08-13
|
||||
@@ -6247,6 +6296,19 @@ stay as decided there.
|
||||
`MAGIC_SYSRQ`: no runtime cost unused, root-only exposure, and root can
|
||||
load modules anyway).
|
||||
|
||||
### Laser commissioning leftovers (item 1), retired 2026-08-31
|
||||
|
||||
Closed: the gap question is answered from the safing chain (the entry
|
||||
above); the confirmation rides `laser.emission-witness`; the flow-band
|
||||
sentence is in the facts bank. Items 2 to 21 are now 1 to 20.
|
||||
|
||||
1. **Laser commissioning leftovers.** Verify the hardware button latch persists
|
||||
across kernel-run gaps mid-job (if OK_2_FIRE drops between motion bursts, the
|
||||
fix is a stream keepalive across armed gaps). The flow check's bands
|
||||
hold from 19 to 27 C, the loop heater's ceiling in a 20 C room, with the
|
||||
margin widening warm; above that only a running tube warms the loop,
|
||||
and the check takes the tube's share off.
|
||||
|
||||
## Reference notes
|
||||
|
||||
### Head-IRQ source validation — the beam-emission hypothesis
|
||||
|
||||
@@ -95,6 +95,8 @@ def sample(ctx):
|
||||
"beam": hw.sysfs_int("head/beam_detect_analog"),
|
||||
"beam_d": hw.sysfs_int("head/beam_detect_digital"),
|
||||
"button_lit": hw.button_lit(),
|
||||
"hv_enable": (st.get("switches") or {}).get("hv_enable"),
|
||||
"button_latch": hw.sysfs_int("cnc/button_latch"),
|
||||
}
|
||||
|
||||
|
||||
@@ -347,14 +349,19 @@ def power_floor(ctx):
|
||||
actions=["button"],
|
||||
steps=["Scrap under the head with 20 mm of free +X and +Y travel; lid closed; exhaust on.",
|
||||
"Press the physical button when it lights white (the arm).",
|
||||
"At the end, confirm the square the laser marked: the one judgment by eye in the "
|
||||
"campaign, the calibration of the sensor witnesses."],
|
||||
description="A 20 mm square outline at S400/F600 in dynamic laser mode: emission_samples "
|
||||
"(the kernel's LASER_ON sample count) goes nonzero during the fire window and "
|
||||
"returns to 0 at Idle, HV current rises during the burn, the head's beam "
|
||||
"detector sees the beam, the armed window is observed, the M2 program end "
|
||||
"disarms promptly at Idle (job-based, not the 60 s idle grace) and the button "
|
||||
"goes dark. The operator confirms the mark.")
|
||||
"At the end, confirm the square the laser marked, all four sides: the one judgment "
|
||||
"by eye in the campaign, the calibration of the sensor witnesses."],
|
||||
description="A 20 mm square outline at S400/F600 in dynamic laser mode with a 2 s dwell "
|
||||
"(G4) between its second and third sides: emission_samples (the kernel's "
|
||||
"LASER_ON sample count) goes nonzero during the fire window and returns to 0 "
|
||||
"at Idle, HV current rises during the burn, the head's beam detector sees the "
|
||||
"beam, the armed window is observed, the M2 program end disarms promptly at "
|
||||
"Idle (job-based, not the 60 s idle grace) and the button goes dark. Across "
|
||||
"the dwell the kernel run ends and restarts: HV_ENABLE drops with the "
|
||||
"charge-pump watchdog and is back for the third side, while the hardware "
|
||||
"button latch stays clear (cnc/button_latch 0 in every armed sample), so the "
|
||||
"second half of the square marks without a second press. The operator "
|
||||
"confirms all four sides.")
|
||||
def emission_witness(ctx):
|
||||
ev = ctx.evidence
|
||||
with ctx.grbl() as g, LiveJob(ctx, g):
|
||||
@@ -367,7 +374,7 @@ def emission_witness(ctx):
|
||||
ctx.check(not base["emission"], "emission_samples nonzero before the job (%s)", base["emission"])
|
||||
ctx.ready(ARM_CUE % "20 mm +X and +Y")
|
||||
job = ["G91", "G21", "M4", "S400",
|
||||
"G1 X20 F600", "G1 Y20 F600", "G1 X-20 F600", "G1 Y-20 F600",
|
||||
"G1 X20 F600", "G1 Y20 F600", "G4 P2", "G1 X-20 F600", "G1 Y-20 F600",
|
||||
"M5", "G90", "M2"]
|
||||
ctx.arm_press()
|
||||
try:
|
||||
@@ -391,6 +398,21 @@ def emission_witness(ctx):
|
||||
"pgood_peak": max((s["pgood"] for s in samples if s["pgood"] is not None), default=None)})
|
||||
ctx.log("emission_samples peak=%s end=%s; hv %s..%s; lid_ir peak %s; armed seen %s",
|
||||
peak, end, ev["hv_min"], ev["hv_max"], ir_peak, armed_seen)
|
||||
# The dwell: a kernel-run gap inside the armed window. The button
|
||||
# latch has no input from the charge-pump watchdog (its SET inputs
|
||||
# are the lid and the SoC lock), so it must read clear through the
|
||||
# gap, while HV_ENABLE drops with the watchdog and returns for the
|
||||
# third side.
|
||||
latch_armed = [s["button_latch"] for s in samples if s["armed"] and s["button_latch"] is not None]
|
||||
first_fire = next((i for i, s in enumerate(samples) if s["emission"]), None)
|
||||
hv_en = [s["hv_enable"] for s in samples[first_fire:]] if first_fire is not None else []
|
||||
dip = next((i for i, v in enumerate(hv_en) if v is False), None)
|
||||
back_lit = dip is not None and any(
|
||||
s["hv_enable"] and s["emission"] for s in samples[first_fire + dip:])
|
||||
ev.update({"button_latch_armed_max": max(latch_armed) if latch_armed else None,
|
||||
"hv_enable_dipped": dip is not None, "hv_enable_back_lit": back_lit})
|
||||
ctx.log("dwell gap: button latch through the armed window max=%s; HV_ENABLE dipped=%s, "
|
||||
"back with emission after it=%s", ev["button_latch_armed_max"], dip is not None, back_lit)
|
||||
# X-3: job-based disarm at Idle after M2
|
||||
dt = wait_disarm(ctx, 75)
|
||||
ev["disarm_after_idle_s"] = round(dt, 1) if dt is not None else None
|
||||
@@ -403,9 +425,14 @@ def emission_witness(ctx):
|
||||
ctx.check(dt is not None and dt < 10.0,
|
||||
"the M2 job did not disarm promptly at Idle (%s s; the idle grace is ~60 s)",
|
||||
ev["disarm_after_idle_s"])
|
||||
ctx.check(latch_armed and max(latch_armed) == 0,
|
||||
"the hardware button latch read SET inside the armed window (max %s over %d samples)",
|
||||
ev["button_latch_armed_max"], len(latch_armed))
|
||||
ctx.check(ev["hv_enable_dipped"], "HV_ENABLE never dropped across the 2 s dwell (the kernel run did not end)")
|
||||
ctx.check(back_lit, "HV_ENABLE did not return with emission after the dwell (the third side ran dark)")
|
||||
judge_beam(ctx, beam)
|
||||
check_button_dark(ctx, ev)
|
||||
ctx.confirm("Did the laser mark a 20 mm square outline on the scrap?")
|
||||
ctx.confirm("Did the laser mark a 20 mm square outline on the scrap, all four sides?")
|
||||
ctx.log("PASS: emission peak %s -> 0, HV %s..%s, beam +%s, disarmed %.1f s after Idle, button "
|
||||
"dark, mark confirmed", peak, ev["hv_min"], ev["hv_max"], beam["delta"], dt)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user