Skip to content

Releases: Loop-Camera/loop-release

TEST BUILD 2 — B&W mode + magenta auto-heal

Choose a tag to compare

TEST PRERELEASE — not for the fleet (no latest.json; the app keeps offering v1.0.1.82). Supersedes v1.0.2-bw-magenta-test.1. Built from loop-firmware combo/bw-mode-magenta-catch @ 0dee75a.

Adds on top of test.1 / v1.0.1.82: the magenta AUTO-HEAL (two layers)

  1. S3 AWB register probe (every 60 s while awake, post-warmup): two masked SCCB reads of 0x3406 (AWB manual latch) + 0x5001 (AWB engine enable). Nothing writes these at runtime, so any unexpected state = the glitch. Heal: direct register fix with readback, escalating to SOFT_RESET only if it doesn't stick. Max 3/boot. (Startup frame-probing was rejected by design: a restart clears the wedge — first frames are the provably-clean moment — and a solo cam can't tell a wedged AWB from a pink scene.)
  2. P4 fleet-gated auto soft-reset: when the per-capture cast telemetry flags EXACTLY ONE cam magenta (rg>22 && bg>22) while ≥2 siblings on the same capture read neutral, fire SENSOR_SOFT_RESET (~150 ms) at that cam. A genuinely pink scene flags all cams and the gate refuses. 5-min/cam cooldown, 6/boot, never during a capture.

Validation status — honest

Deployed + running on the bench P4X + 4 cams; both layers compile clean and the P4 gate is pure arithmetic over the already-proven cast telemetry. The end-to-end induced-wedge proof (cam_setreg AWB latch + magenta gains → detect → heal → neutral) is built but blocked: the bench SD card died mid-run (terminal 0x107 wedge, physical reseat needed) — without SD there are no saves, so the telemetry path can't execute. The harness re-runs immediately after a card reseat. Watch for MAGENTA AUTO-HEAL / AWB PROBE log lines in the field.

Promotable to v1.0.1.83 (fleet) once validated.

TEST BUILD — B&W mode + magenta-cast detection

Choose a tag to compare

TEST PRERELEASE — not for the fleet. No `latest.json` is included and this is marked prerelease, so the companion app will NOT offer it; production stays on v1.0.1.81. Built from `loop-firmware` branch `combo/bw-mode-magenta-catch` (= docs/bw-mode-research cb361b4 + investigate/magenta-cam-frames 407c03d, merged clean).

What's in it

B&W Mode (docs/black-and-white-mode.md)

  • Settings → slot 6 "B&W Mode" toggle: the 4 S3 cams shoot grayscale (OV5640 SDE, post-warmup wedge-guarded apply — a marginal sensor reverts to color rather than wedge) AND the viewfinder goes gray (ISP saturation 0; user saturation restored on toggle-off).
  • Camera-entry reconcile keeps cams in sync (IDLE byte 73); mode persists across sleep/reboot on both sides (NVS).
  • Serial: set_bw on|off, get_bw, cam_bw_get. e2e test 101.
  • Validated: reconcile 4/4 both directions, capture 4/4, pixel-proof pure gray (max|R−G|=0), JPEGs ~15% smaller on a dim bench, encode 68s vs 75s.
  • The cams need the embedded S3 blob — the boot reconcile auto-OTAs them on first boot of this image.

Magenta-cast detection (docs/magenta-cam-investigation.md)

  • Per-capture telemetry: lps cast posN: rg=±X bg=±Y per cam on every encode + MAGENTA-CAST suspect posN WARN when the magenta signature (rg>22 && bg>22) appears — catches the "one cam goes magenta until restart" field bug in the act with cam attribution.
  • On-device cast_check <path> probe + tests/e2e/_cast_scan.py historical sweep.
  • Baseline (117 JPEGs): all cams median rg +13/+14, bg≈0; zero suspects. If you see magenta: the logs will name the cam — cam_sensor_soft_reset N (~150 ms) should clear it; please note whether it does (that confirms the remediation for auto-heal).

Flashing

  • P4X: loop.bin / loop-p4x.bin — USB esptool, or scripts/ota_serial.py --image / the app's chunked /firmware/install.
  • Plain P4 (v1.3): loop-p4.bin (+ loop-p4-bootloader.bin if bootloader flash needed).

v1.0.1.91

Choose a tag to compare

@NickEngmann NickEngmann released this 15 Aug 01:32

v1.0.1.91 — PR #96 merge (field-bug fixes) + v1.3 mp4-memory hardening

Built manually from main @ 95f0d20 (merge of PR #96, fix/idle-sleep-and-cycle-speed).

Field-bug fixes (PR #96)

  • .lps playback speed no longer varies between album entries — palindrome cycle normalized to a uniform 680 ms regardless of 2/3/4-camera capture width (loop_normalized_delays, applied to both the .mp4 sidecar timings and the .lps writer).
  • Encoder-hold force-sleep now always wakes on the rotary encoder — encode-time viewfinder pause/resume chain hardened (REQBUFS-before-realloc resume order, 1 Hz resume retry with cache yield). Soak-validated: 11/11 sleep/wake cycles, wakes 1–5.6 s.
  • Camera modules reliably sleep on idle — sleep verify re-sends up to 8 rounds with a per-cam mask + explicit GAVE UP verdict; the S3 do_sleep never refuses (EXT0-arm failure falls back to EXT1/10-min timer wake, new EXT0_FAIL sleep-diag); trigger auto-recovery gated so it can't wake a sleeping fleet.

v1.3 mp4-memory hardening (post-.90, found on the plain-P4 bench)

  • mp4 create ladder parks the bitstream buffer and retries at NATIVE before ever falling to half-res — rotate re-encodes on the v1.3 were silently downscaling then failing 0x106.
  • Rotate worker defers while the foreground encode queue is busy — two concurrent mp4 encodes don't fit the v1.3's PSRAM.

Validation

Full 81-test on-device e2e union across a P4X and a plain-P4 v1.3 (parallel forward/reverse runs + targeted re-runs); all residual failures triaged to rig/unit state — details on loop-firmware PR #96.

Variant Image Notes
P4X (chip rev v3.x) loop-p4x.bin (= loop.bin) default fleet image
plain P4 (chip rev v1.3) loop-p4.bin + loop-p4-bootloader.bin

v1.0.1.90 — idle-sleep reliability + uniform wiggle speed

Choose a tag to compare

@NickEngmann NickEngmann released this 14 Aug 17:48

Built from the PR #96 branch (idle-sleep + cycle-normalization fixes). Bench-soaked: 11/11 idle cycles with all cameras asleep, wakes 1–5.6 s, playback pacing exact. Full two-camera e2e regression in progress on this exact content — results on the PR.

  • Camera modules now reliably sleep on idle. Three stacked fixes for the "modules stay hot / battery drains in idle" bug: the dropped-capture auto-recovery no longer fires its wake pulse after you've left or slept the device; the sleep-verify retries much longer, names defiant cameras in the log, and shouts when it gives up; and the camera-module firmware NEVER refuses to sleep any more — if its preferred wake source fails to arm it sleeps on a fallback (with a 10-minute timer backstop, so it can never become unwakeable) and reports the condition (sleep_diag=EXT0_FAIL).
  • Every wigglegram now plays at the same speed. Partial captures (2 or 3 cameras) used to cycle up to 2.4× faster than 4-camera ones — the "album speed feels doubled or tripled, different every visit" bug. Per-frame timing is now normalized so every capture cycles in exactly 680 ms, in both the album preview and the exported MP4. Existing captures pick up the new timing on any re-encode (e.g. Rotate); new captures are right from the start.
  • Cameras auto-update their camera-module (S3) firmware on first boot if needed (~2 min on the splash screen).

v1.0.1.89 — mp4-era file hygiene

Choose a tag to compare

@NickEngmann NickEngmann released this 09 Aug 03:44

Small hygiene follow-up to v1.0.1.88 (PR #92 merged to main).

  • Boot recovery sweeps stranded encoder working files (<stem>.mp4.smp / .mp4.part) that a hard reset mid-encode leaves behind — previously nothing ever removed them once the capture's .mp4 existed.
  • Deleting a capture now removes its .mp4 (and any working files). The cleanup list predated the mp4 switch, so deleting an mp4-era capture stranded the .mp4, left a husk directory, and could falsely raise the red SD-ERROR overlay on a healthy card.

Validated on the P4X bench: the boot sweep fired on real litter, and the previously-failing e2e checks (88, 106) pass on this build. Full fast suite green on this firmware line.

v1.0.1.88 — MP4 encode reliability: native-res guaranteed

Choose a tag to compare

@NickEngmann NickEngmann released this 09 Aug 00:34

MP4-first reliability release (branch fix/wiggle-record-mp4-first merged via PR #90, stacked on the mp4-first + Color Match work).

  • Native-resolution MP4 encodes are no longer a memory coin flip. The hardware H.264 encoder needs a ~5 MB contiguous buffer per encode; with the viewfinder's capture buffers mapped, the heap's largest free block hovered right at that size — one suite run logged 32 silent half-res fallbacks and rotate re-encode failures. Encodes now pause the viewfinder (the proven idle-sleep close, ~7.5 MB freed; camera-page entry resumes it), the resume path allocates its big V4L2 buffers first, and a 1 Hz retry self-heals a resume that lands mid-encode.
  • Rotate 180 works reliably again (the 0x101/0x106 re-encode failures were the same memory mechanism).
  • Wiggle records over the app API now describe the .mp4 artifact (name/size/download), not just the legacy .gif.
  • Exported MP4s thumbnail correctly on phones (conformant SPS + avcC — carried in from v1.0.1.87-era branch work, now merged).
  • Full on-device regression: 80/80 e2e tests + host suites 21/21 on the P4X bench.

Cameras auto-update companions (S3/C6) on first boot if needed.

v1.0.1.87 — AWB green-wedge telemetry + capture-time heal

Choose a tag to compare

@NickEngmann NickEngmann released this 02 Aug 01:56

Follow-up to v1.0.1.86's neon hotfix, focused on the green-frame source.

  • Root cause pinned with live evidence: the whole-frame green casts are the flash-lit keeper frames of dark scenes — AWB starves toward unity in darkness and its re-convergence races the ~2 s flash lead, so cameras whose keeper lands early ship a partially-converged green frame. (A register-latch heal was tested and ruled out live — the readable AWB gain registers do not carry the live auto state.)
  • The v1.0.1.86 monochrome rescue was validated on naturally occurring wedges: 100% of wedged frames were caught and rendered clean.
  • This release adds per-camera telemetry (cam_status … awb_gheal=), GREEN-CAST log warnings for field attribution, and a budget-capped capture-time AWB re-kick.
  • Cameras auto-update to the new S3 firmware on first boot (~2 minutes on the splash screen).

v1.0.1.86 — hotfix: neon artifacts in low-light shots

Choose a tag to compare

@NickEngmann NickEngmann released this 01 Aug 22:51

Hotfix for the v1.0.1.85 field report: bright neon artifacts across low-light pictures. Two mechanisms, both fixed:

  1. Chroma-speckle amplification — the low-light lift scaled all channels by the per-pixel gain (up to 4–6× in deep shadows), turning dark chroma noise into saturated confetti. The lift now decomposes each pixel around its luma: luma gets the full lift, chroma is capped at 1.5×. Real-capture A/B: neon pixels 6.61% → 0.09% of the worst dark frame; strong colors at moderate lifts unchanged.
  2. AWB-wedge whole-frame casts — some cameras intermittently ship frames with white balance effectively unapplied (a uniform green cast, the sibling of the known magenta wedge; pre-existing, previously hidden because low-light output stayed dark). These frames are now detected (uniform ±60 DN cast on both channels — no real scene is that uniform) and rendered as clean monochrome instead of glowing neon (real-capture proof: solid green rg=−136 → neutral +2).

The low-light improvements themselves are unchanged: edge-preserving noise reduction, hybrid brightness lift (dark shots reach the target instead of staying at ~half), and the dark-scene 8× analog gain ceiling.

New regression tests: 10 host tests including a neon guard that fails on the v1.0.1.85 code, plus a color-validation rule for all future pixel-pipeline changes. Camera (S3) firmware unchanged from v1.0.1.85 — no camera reflash on boot.

v1.0.1.85 — FPN residual refine + low-light overhaul

Choose a tag to compare

@NickEngmann NickEngmann released this 01 Aug 15:20

Vertical banding — round 2 (works with ZERO calibration)

  • Per-capture residual refine ("bootstrap destripe"): at encode time each frame's residual column offset is estimated from its own dark flat rows and removed — uncalibrated devices get ~80% of the banding fix immediately (real-capture: band p95 10.6→2.3 DN), and calibrated devices get the full-resolution/PRNU residue the 1280-bin profile can't represent. Engage-gated: clean frames stay bit-identical. Escape hatch: set_fpn_refine off.
  • FPN auto-calibration now actually arms on plain-P4 v1.3: the calibration tasks spawn with PSRAM stacks (the 16 KB internal stack never fit on v1.3 — profiles could never be stored).
  • Rotated re-encodes no longer mis-apply the FPN profile (rotation ran before the column mapping — it was adding banding on album-ROTATE captures).

Low-light shots

  • New encode-side low-light pipeline (lowlight.c): edge-preserving noise reduction (flat noise 0.65→0.27 DN, JPEG blocking 1.68→1.33) + a hybrid linear+gamma lift that reaches the target brightness the old 3.0× linear clamp never could — while capping total lift at 4.5× so a black room stays black instead of gray fog. Ordered-dither requantization prevents shadow posterization. Escape hatch: set_lowlight off.
  • Dark-scene 8× analog gain ceiling (camera side): the P4 raises the OV5640 analog gain ceiling from 2× to 8× when the scene is dark (bench-measured ~3× more source signal, digital lift dropped from a pegged 300% to ~150%), reverting to 2× in bright scenes. Rides the same hysteresis as adaptive JPEG quality; the refine + NR absorb the noise/banding cost.

Validation

134+ host unit tests (incl. 11 new), host_encode 114/0, fast e2e 35/39 on the bench (all 4 non-passes triaged as known flakes / transients that pass standalone), on-device A/B on two P4X rigs incl. night captures. Cameras auto-update to S3 build fw_crc 0xb12c0e87 on first boot.

Loop Firmware v1.0.1.84

Choose a tag to compare

@NickEngmann NickEngmann released this 30 Jul 10:47

Loop Firmware v1.0.1.84

Everything merged since v1.0.1.83 (built + published manually — Actions credits exhausted; same pipeline, same assets):

Fixes

  • Vertical banding (incl. B&W mode) — the per-column FPN correction shipped default-ON but unarmed (no stored profile). Profiles now auto-calibrate when the camera sits idle ~45 s in a dark scene: amber CALIBRATING… badge on screen, idle-sleep held during the run, aborts on page-leave or user capture, never overwrites existing profiles, bounded 3 attempts/boot. Validated: −81%/−90% band metric on fresh captures. (#82)
  • Auto-cal lighting guard — the run aborts (nothing stored) the moment room lighting changes mid-calibration; per-frame check closes the run-average dilution hole. Live-validated against actual sunrise. (#83)
  • Residual magenta frames — pre-capture AWB register sanity check guarantees a register-latched wedge can never ship a frame (sync-first: heal + shoot immediately, zero added inter-cam skew); POSTCAP check + 15 s probe with a bigger heal budget. (#81)
  • Battery — poll task kicked on camera-page entry (stale empty icon after charger-plug); raw MP2624 REG08/REG09 published for charge-fault naming; vc 12-pin wiring docs. (#80)

Carried from the 07-28/29 merge train (first release containing them)

  • Wi-Fi transfer speed ~3× — BLE advertising pauses during live app sessions (in-app 5.4–5.8 MB GIF export: ~30 s → ~8–12 s); stale sessions decay via WS probe so the advert always resumes. (#79)
  • Post-Connected SD save wedge — APP_CONN radio enter/leave serialized + probe-gated reboot safety net. (#78, via #79)
  • Honest pairing states + SoftAP credentials on-screen — no more false "Connected" on a failed Wi-Fi join; the pairing screen shows ssid + password. (#78, via #79)
  • LPS album self-heal, <6 s menu-bounce sleep-restore, UI overlay fixes, S3 control-queue hardening. (#77)