Skip to content

Patternflow v3.3.0 — a panel you can actually calibrate

Choose a tag to compare

@engmung engmung released this 12 Aug 02:27

Color, end to end: perceptual ramps in the editor and a panel you can actually calibrate. Hardware unchanged — v3.0 board and case carry over as-is.

Backfilled tag. This shipped as the stock image on 2026-08-09 but was never tagged, which left the README pointing at a release page that did not exist.

Added

  • Runtime display calibration (#287). White balance, gamma and saturation were compile-time constants, so finding a number cost a reflash per guess. They are runtime state now, tunable live over GET /api/display while looking at the panel. Values are session-only; the converged ones go back into config.h as the shipped defaults.
  • Calibration test card, as an overlay rather than a pattern — knob browsing stays a curated list. ?screen=0..3 draws it over the running pattern (which freezes underneath) and ?screen=-1 resumes; a long-press on K4 or any pattern switch also dismisses it, so a closed browser tab can never strand the panel on a test screen. Four screens: white field, a 16-step staircase over a smooth gradient, color bars at full and half drive, and sRGB-versus-OKLab ramp pairs on the actual LEDs.
  • Panel tuner — sliders driving /api/display beside a canvas rendering the same test frames in raw sRGB. The reference is the point: you cannot judge a color against a memory, only against another color. Generates a config.h block once the values settle.
  • Perceptual color ramps in Pattern Lab and the community sandbox — oklab, oklch short and oklch long. Blending complementary stops in sRGB collapses the middle into grey and sweeping hue in HSV makes lightness pulse; interpolating in OKLab does neither. Because ramps bake to a 256-entry lookup table web-side, the new modes reached the firmware and .pfm builds with no device-side change.
  • LED panel compatibility guide (#258, #259). A panel matching our spec line for line can still stay completely black, because HUB75E is a connector and not a protocol — the driver ICs decide. The driver IC is essentially never in the listing (we audited our own: it appears zero times in the title, spec table, marketplace summary and PDF manual), so the guide leads with what actually works — reading buyer reviews from people running it off an ESP32 — then asking the seller. Opened up by @SimonePDA, who hit the failure and researched it properly.
  • PANEL_PROFILE covers all six library drivers instead of two.
  • Remote pattern selectionGET /api/patterns/select?name=|index=.

Changed

  • Shipped color defaults are one panel's measured numbers, not plausible ones: LED_WB 0.930/1.000/0.975 and LED_SAT_BOOST 1.62. The saturation direction reversed the theory that predicted it — narrow-band LED primaries cover more than sRGB, which argues for cutting saturation, but beside a monitor showing the same frame the panel reads washed out. Existing devices will look different after this update — more saturated, less warm. Panels vary; tune your own with /api/display.
  • Encoder acceleration removed — one detent, one step (#262). A fast spin used to multiply each detent ×2 to ×5. Compared against a linear build with four curves live at once, linear won outright: the multiplier was worst on the parameter that most needs landing on a value, since Origin's Mode knob picks a discrete preset and a quick turn skipped five at a time.
  • Knob travel derives from the parameter's range. It was a fixed per-knob constant that never looked at min/max, so a 0..1 knob crossed in one turn while a 0..100 knob needed a hundred. Travel is now (max - min) per two turns. Existing presets keep their compiled-in constants.

Fixed

  • Calibration tables no longer sit in internal DRAM (#288). The test card's ramp tables shipped as a 1.5 KB namespace static — the exact mistake core_mem.h exists to prevent. With them resident every console page truncated at ~5.6 KB and module uploads failed. They allocate from PSRAM now, and /patterns delivers its full 16 KB in 0.4 s.
  • Encoder decoder resynced onto bounced states (#262). The quadrature ISR updated its reference on transitions that cannot physically happen, so a bounced jump moved the decoder to the wrong phase. Illegal transitions are discarded now, plus a time filter — the A/B lines have no RC filter and only weak internal pull-ups.
  • ENCODER_CLICKS_PER_TURN was 20; the reference encoder has 24. It sat next to a comment promising one web rotation equals one physical turn, so the preview it claimed to mirror was 20% out of step. Sourcing a different encoder? Generic EC11s ship as 20, 24 or 30, and this constant has to match what is in the build.
  • Panel-profile guidance was backwardsconfig.h sent anyone holding the reference panel to change a setting they don't need. The rule is now empirical: stay on the default unless the panel comes up completely dark.
  • Assorted documentation corrections: brightness is K1 long-press not K2, the removed Pattern/Video content mode, the presets/ layout, v2 build-guide flashing ports, panel mounting screws, and the v2 BOM's power-cable note.

Superseded by v3.4.0.