From 64301d322190a6fc9a4ca3053c7e015abebe2fcc Mon Sep 17 00:00:00 2001 From: ScottW514 Date: Wed, 9 Sep 2026 15:32:54 -0400 Subject: [PATCH] Keep the configuration files inside /data/forgefirm; pin the three components ForgeFIRM's own files live under /data/forgefirm; two configuration files did not. The machine settings sat at /data/forgefirm.conf, in the root of /data beside the factory's own files, and the cloud-mode configuration sat at /data/etc/gfhome.conf, inside a directory the factory owns. Both move: /data/forgefirm.conf -> /data/forgefirm/forgefirm.conf /data/etc/gfhome.conf -> /data/forgefirm/gfhome.conf There is no migration: only the bench has ever run this firmware. /data/etc now holds only the factory's wpa_supplicant.conf. The acceptance check of the file modes reads the settings file at its new path, and the two bench tools that read it directly follow. The pins move to the revisions that carry the change, forgectrl also bringing the fix that reads the module's disabled state as idle: forgectrl 468ee21 (0.1.12) grblhal-glowforge 9ee624b (0.1.10) forgefirm-app 56f134a (0.1.28+git) The lock moves meta-openglow to b7ad6d9, which pins python3-gfhardware on the same revision. The four upstream layers stay where they were: `kas lock --update` moves every floating repository, and a release is not the place to take poky, meta-openembedded and meta-freescale along for the ride. --- forgetest/forgetest/suite/image.py | 2 +- kas/forgefirm-glowforge.lock.yml | 2 +- meta-forgefirm/recipes-extended/rsyslog/rsyslog/rsyslog.conf | 2 +- meta-forgefirm/recipes-forgefirm/forgectrl/forgectrl-pin.inc | 4 ++-- .../recipes-forgefirm/forgefirm-app/forgefirm-app-pin.inc | 4 ++-- .../grblhal-glowforge/grblhal-glowforge-pin.inc | 4 ++-- meta-forgefirm/recipes-forgefirm/images/forgefirm-image.bb | 2 +- scripts/bench/README.md | 2 +- scripts/bench/gfbench.py | 2 +- scripts/bench/live_fire_drills.py | 2 +- 10 files changed, 13 insertions(+), 13 deletions(-) diff --git a/forgetest/forgetest/suite/image.py b/forgetest/forgetest/suite/image.py index b62a8c6..1431732 100644 --- a/forgetest/forgetest/suite/image.py +++ b/forgetest/forgetest/suite/image.py @@ -236,7 +236,7 @@ def image_health(ctx): ctx.check(not user_wd, "a userspace watchdog daemon is running: %s", user_wd) # 7. file modes and space - for path in ("/data/forgefirm/panel.token", "/data/forgefirm.conf"): + for path in ("/data/forgefirm/panel.token", "/data/forgefirm/forgefirm.conf"): if os.path.exists(path): m = stat.S_IMODE(os.stat(path).st_mode) ev[path] = "%o" % m diff --git a/kas/forgefirm-glowforge.lock.yml b/kas/forgefirm-glowforge.lock.yml index 5613b03..7906aa3 100644 --- a/kas/forgefirm-glowforge.lock.yml +++ b/kas/forgefirm-glowforge.lock.yml @@ -11,4 +11,4 @@ overrides: meta-freescale-distro: commit: b9d6a5d9931922558046d230c1f5f4ef6ee72345 meta-openglow: - commit: d655e1e58c97224236f21472b02cb19f32eab982 + commit: b7ad6d9377fbb4215dc4d898837906b06b47e5e9 diff --git a/meta-forgefirm/recipes-extended/rsyslog/rsyslog/rsyslog.conf b/meta-forgefirm/recipes-extended/rsyslog/rsyslog/rsyslog.conf index fd421b2..92a0d38 100644 --- a/meta-forgefirm/recipes-extended/rsyslog/rsyslog/rsyslog.conf +++ b/meta-forgefirm/recipes-extended/rsyslog/rsyslog/rsyslog.conf @@ -3,7 +3,7 @@ # rsyslog is the only log writer on the machine. Every ForgeFIRM process # (forgectrl, grblHAL, gfcloud, gfhome), the kernel, and everything else # route to their own directory under /data/log/forgefirm. The per-logger -# disk and remote levels come from /data/forgefirm.conf and are rendered +# disk and remote levels come from /data/forgefirm/forgefirm.conf and are rendered # into the included rules file at every boot by `forgectrl # --render-syslog` (see the forgefirm-logging init script), so a change # made in the control panel applies at the next reboot. diff --git a/meta-forgefirm/recipes-forgefirm/forgectrl/forgectrl-pin.inc b/meta-forgefirm/recipes-forgefirm/forgectrl/forgectrl-pin.inc index 750fac9..f499d56 100644 --- a/meta-forgefirm/recipes-forgefirm/forgectrl/forgectrl-pin.inc +++ b/meta-forgefirm/recipes-forgefirm/forgectrl/forgectrl-pin.inc @@ -2,5 +2,5 @@ # only SRCREV and PV here - the image manifest leaves *-pin.inc out of the # layer content hash because the component entry already identifies the # pinned source (forgefirm-image-manifest.bbclass). -SRCREV = "439a8889ce0edb8ca8ab83f02bd3c3e0f09dd91a" -PV = "0.1.11" +SRCREV = "468ee215dd1148b92c979decacecc41aa6a75ccf" +PV = "0.1.12" diff --git a/meta-forgefirm/recipes-forgefirm/forgefirm-app/forgefirm-app-pin.inc b/meta-forgefirm/recipes-forgefirm/forgefirm-app/forgefirm-app-pin.inc index 835f052..18c9e3c 100644 --- a/meta-forgefirm/recipes-forgefirm/forgefirm-app/forgefirm-app-pin.inc +++ b/meta-forgefirm/recipes-forgefirm/forgefirm-app/forgefirm-app-pin.inc @@ -4,9 +4,9 @@ # because the component entry already identifies the pinned source # (forgefirm-image-manifest.bbclass). The python3-gfhardware recipe in # meta-glowforge-bsp pins the same repository; move both together. -SRCREV = "53d57f7c84fd314012f21bbbee883dde95353ded" +SRCREV = "56f134a1e6393a2096c16e8226027fbbd38d79c7" # Bump PV with every SRCREV move: the hash-derived package version is not # monotonic on its own and buildhistory QA fails the build when it sorts # backwards. -PV = "0.1.27+git" +PV = "0.1.28+git" diff --git a/meta-forgefirm/recipes-forgefirm/grblhal-glowforge/grblhal-glowforge-pin.inc b/meta-forgefirm/recipes-forgefirm/grblhal-glowforge/grblhal-glowforge-pin.inc index 80de649..ff4f944 100644 --- a/meta-forgefirm/recipes-forgefirm/grblhal-glowforge/grblhal-glowforge-pin.inc +++ b/meta-forgefirm/recipes-forgefirm/grblhal-glowforge/grblhal-glowforge-pin.inc @@ -2,5 +2,5 @@ # changes; keep only SRCREV and PV here - the image manifest leaves # *-pin.inc out of the layer content hash because the component entry # already identifies the pinned source (forgefirm-image-manifest.bbclass). -SRCREV = "97be92bbc8443ff8c4a3176fa2594cd6828c1c65" -PV = "0.1.9" +SRCREV = "9ee624bbc1d1fd929f1f5587b6fc6acaa13a4561" +PV = "0.1.10" diff --git a/meta-forgefirm/recipes-forgefirm/images/forgefirm-image.bb b/meta-forgefirm/recipes-forgefirm/images/forgefirm-image.bb index 378981e..9287c22 100644 --- a/meta-forgefirm/recipes-forgefirm/images/forgefirm-image.bb +++ b/meta-forgefirm/recipes-forgefirm/images/forgefirm-image.bb @@ -28,7 +28,7 @@ IMAGE_INSTALL:remove = "python3 ${FORGEFIRM_RELEASE_TRIM}" # broker, cooling engine, cameras, telemetry, settings, diagnostics, web # control panel, and A/B updates. # gfhome: one-shot Glowforge web-service homing, invoked by the controller -# for $H when homing_mode = gfcloud (/data/forgefirm.conf). +# for $H when homing_mode = gfcloud (/data/forgefirm/forgefirm.conf). # gfcloud: full Glowforge web-service controller daemon (the factory cloud # experience), started when controller_mode = cloud - mutually exclusive with # grblHAL. Pulls python3-ffmachine (shared web-service machine glue). diff --git a/scripts/bench/README.md b/scripts/bench/README.md index ce63f3c..4666272 100644 --- a/scripts/bench/README.md +++ b/scripts/bench/README.md @@ -40,7 +40,7 @@ page's takeover does that; from a host, stop them first. | `raster_dry.py` | A dry raster at top speed at each XY microstep mode (runs on the board; the controller in GRBL mode, idle, no other Grbl client): per mode given (default 8, 16, 32) it stores `xy_microsteps` through forgectrl, waits for the restarted controller, streams 60 passes of 150 mm at F12000 with the laser off, and reports the peak feed, the controller CPU, the kernel counters against the start, `cnc/underruns` and any clamped-event line. Needs 150 mm of free +X and 12 mm of free +Y travel. Ends at x8. | | `xy_pattern_accel.py` | The XY microstep modes by the head accelerometer with the machine silent (runs on the board; the machine homed and at home, the lid closed, no other Grbl client): per mode it takes the cooling engine's quiet hold with the pump (`POST /cool/quiet?on=1&pump=1`: every fan, the pump and the TEC off), waits the fixed 10 s, samples the LIS2HH12 over `/dev/i2c-3` in one SMBus block transaction per reading at about 600 Hz, and runs the pattern from home at F12000: to (18, 9) in, to (9, 9) in, a 9 in circle from its mid-bottom back to (9, 9), to (9, 0), home. Reports the cruise-window RMS and peak-to-peak per leg and overall, the leg times, the kernel counters against home and `cnc/underruns`; JSON with the trace in the bench data directory. Ends at x8. | | `arc_tolerance_sweep.py` | How fine an arc the controller can plan (runs on the board; the machine homed and at home, the lid closed, no other Grbl client, the machine silent through the quiet hold): a `$12` ladder on the 9 in circle at F12000 at the mode given (`--mode`, default 16). Per rung: the chords and the chord boundaries a second, the circle time against the ideal, the lowest feed mid-circle and the fewest free planner blocks, the controller CPU, clamped events, underruns and the accelerometer's cruise RMS. `$12` goes back to what it was on every exit path; the head returns home. | -| `gfbench.py` | Not a tool: the helper the board/host tools share - `HOST`/`LOCAL` from `GF_HOST`, `board(cmd)` (local `sh -c` or ssh), the factory coolant conversion `degc()`, `data_path()` (`FORGETEST_BENCH_DATA` or next to the tool), forgectrl's HTTP API with the panel token, `setting(key)` (from forgectrl, or from `/data/forgefirm.conf` on the board while forgectrl is stopped). | +| `gfbench.py` | Not a tool: the helper the board/host tools share - `HOST`/`LOCAL` from `GF_HOST`, `board(cmd)` (local `sh -c` or ssh), the factory coolant conversion `degc()`, `data_path()` (`FORGETEST_BENCH_DATA` or next to the tool), forgectrl's HTTP API with the panel token, `setting(key)` (from forgectrl, or from `/data/forgefirm/forgefirm.conf` on the board while forgectrl is stopped). | | `lens_travel.py` | Lens travel drill (runs on the board; stops the controller through forgectrl and restarts it; lens motion only): steps the lens over sysfs the way the focus card's lens home does and counts, per condition and round, the hall's hysteresis band (down off the rising edge until the hall leaves home, back up until it reads home), the rising edge's height above the bottom stop after a drive onto it, and the top stop's height above the edge (a drive up, down until the hall leaves home, back up; the difference). Conditions: the card's half-step drive onto the stop, a short drive, a long one, the factory's full-step home mode; `--ladder` drives a list of half-step descents below the leave-home point and counts each back (exact until the stop, short by an even number after a stall), `--current` picks the run current, the hold current, or hold down / run up, `--settle` and `--cadence` vary the timing; `--park bottom|top|edge-N|edge+N` holds the lens there for a depth-gauge reading with the controller in standby, `--park edge` returns it to the rising edge and restarts the controller. Stall drills on the bench reference machine only. The posture found is put back. | | `lens_stop_accel.py` | Lens stop detection by the head accelerometer (runs on the board; stops the controller through forgectrl and restarts it; lens motion only; stall drills on the bench reference machine only): reads the LIS2HH12 straight over `/dev/i2c-3` in six-byte bursts at 800 Hz (the iio path waits a sample period per read), steps the lens one half-step at a time from the hall's rising edge toward each stop and past it, and prints per step the peak-to-peak on each axis. A free step rings strongly on every second half-step; at a stop the ring dies, and a rotor slip a few steps later is a burst three times any free ring. `--find N` runs the contact rule N times per stop (a strong-parity step ringing under `--thresh`, or a burst over four times it, calls contact; the lens backs off `--back` and the count home proves no slip). `--save` keeps the per-step sample traces as JSON. | | `fan_test.py` | Fan/coolant bench (board or host; controller running): snapshots fan PWMs/tachs/temps, drives M8 → cut fans, M9 → cooldown → idle, verifying via tach readbacks. | diff --git a/scripts/bench/gfbench.py b/scripts/bench/gfbench.py index 3703fa3..9e1465e 100644 --- a/scripts/bench/gfbench.py +++ b/scripts/bench/gfbench.py @@ -144,7 +144,7 @@ def forgectrl_post(path, **kw): return forgectrl_request("POST", path, **kw) -SETTINGS_FILE = "/data/forgefirm.conf" +SETTINGS_FILE = "/data/forgefirm/forgefirm.conf" def setting(key, default=None): diff --git a/scripts/bench/live_fire_drills.py b/scripts/bench/live_fire_drills.py index b5ec69c..f0dda46 100644 --- a/scripts/bench/live_fire_drills.py +++ b/scripts/bench/live_fire_drills.py @@ -657,7 +657,7 @@ DLADDER_LEN = 25.0 # mm of burn per rung DLADDER_PITCH = 3.0 # mm between rungs STREAM_RATE_HZ = 28160 # machine tick (GFSINK_RATE default) PWM_PERIOD = 127 # 7-bit power byte against PWMSAR -CONF = os.environ.get('GFHOME_CONF') or '/data/forgefirm.conf' +CONF = os.environ.get('GFHOME_CONF') or '/data/forgefirm/forgefirm.conf' PULSE_MIN_KEY = 'laser_pulse_min_ticks' PULSE_MIN_DEFAULT = 3 # glowforge_laser.c PULSE_MIN_TICKS_DEFAULT