Repository navigation
Conversation
Lights around a display now glow the color of the picture nearest them: a video source publishes one decoded RGB frame per tick, and an effect gives each light the mean of the rectangle mapping to it. The frame comes from a synthesized test pattern or a binary PPM, so the whole path is reviewable and testable on a desktop build. Capturing a real picture from an HDMI grabber over USB follows in its own change. **Core** - VideoService: two sources, a strict Netpbm P6 header parser, and a one-active-source seat so a service added or removed at runtime hands over rather than going dark - VideoFrame: the frame contract, borrowing the producer's buffer for one tick - Every frame carries its tone curve, sRGB here, so a consumer averages light rather than encoded bytes **Light domain** - AmbilightEffect: a per-light box filter averaged in LINEAR light, then encoded once per light, so a part-lit zone reads as bright rather than as a dim mush - Positions reaching no LED are skipped, which on a border layout is most of the box, so a backlight strip costs its perimeter rather than its bounding box - edgeDepth widens the outermost zones past the overscan junk; detectBlackBars moves them inside a letterbox, which edgeDepth cannot do - Smoothing keeps 8.8 fixed-point state per channel, with snapAbove letting a cut land whole - MappingLUT: hasDestination(), the one question the effect asks per position **Tests** - unit_VideoService: 13 cases over the header grammar, the seat election and the pattern's sweep rate - unit_AmbilightEffect: 23 cases over orientation, coverage, the linear-light mean, smoothing in both directions, bar detection and the sparse-mapping skip, with a hollow-rectangle layout local to the file - scenario_Video_source: add, configure and remove the service and its consumer under a running pipeline, which also pins the type registry, since the runner constructs every module through src/module_types.cpp **Docs/CI** - A Video card under core/services.md and an Ambilight card under light/effects.md, each with its details section - screenshot_modules captures both A strip is placed on a wall's edge pixels by the MoonLive library's backlight.mll, so this adds no layout. docgen: appendix lines 5617 to 5643, for the three new headers, which is the one rule that rises. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The video source gains a third option: an HDMI grabber presenting itself as a UVC webcam, streaming MJPEG that the P4's JPEG hardware decodes. A console or a PC on the grabber's input now drives the lights directly. Every other target links a stub whose init fails, which the service reports as a status rather than an error. **Platform** - A UVC capture seam in platform.h: the device handle, the advertised format rows, the frame accessor and the drop counters - platform_esp32_usbvideo.cpp: the UVC stream and the hardware JPEG decode across three threads, with the decode off the render tick and the newest frame winning when one is still pending - Buffers belong to the platform for the life of one open, so a published frame borrows rather than copies, and the renderer drops it before deinit - Bulk payload headers are stripped by a stride read off the first header, which usb_host_uvc leaves in when a device's payload is a multiple of the packet size - Gated on the chip AND both SoC capabilities, since only the P4 has a High-Speed USB PHY and a JPEG decoder **Core** - VideoService: the usb source, the offered-format picker, staleMs, and hdr with the PQ and HLG curves, since MJPEG carries no HDR metadata and a grabber strips what the console sends - A hotplug is noticed by one atomic load a second, answered by a tree rebuild on the thread that may open the device **Tests** - unit_VideoService: the capture-capability pair and the PQ curve recovering a measured source's linear ratio **Docs/CI** - The Video card gains its four capture controls; details gain the P4 requirement, format choice, HDR and staleness - esp32: the usb_host_uvc component for the P4 alone, and a 2 KB control-transfer buffer, without which an MS2130 never enumerates - .clangd points the ESP32 platform directory at a firmware compile database Built for esp32p4rev3-eth-wifi, which links the UVC driver, and for esp32s3-n16r8, which links stubs and no component. docgen: appendix lines 5643 to 5669, four for VideoService's restored capture sections. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
An LED's three emitters are not equally efficient, so a neutral triple can render with a cast: on an SK6812 the green die runs hot and grey scenes come out tinted. Four trims correct it at the output, once per strip, rather than leaving every effect to guess. **Light domain** - balanceRed, balanceGreen and balanceBlue pull one die down to meet the others. Trim DOWN only, since there is no headroom above 255 and raising a channel clips rather than balances - whiteLevel trims the white die, which the RGB trims cannot reach: a white phosphor is separate hardware, often brighter than the trio beside it - Folded into the SAME table fill that applies the curve, as a linear pre-scale, so the hot path stays one lookup per channel and the curve still lands last - briLut carries a row per trim, and the 16-bit table a driver allocates for fine channels carries the same rows, so a 16-bit output is balanced exactly as an 8-bit one is - Amber and UV read an untrimmed row, being their own dies that an RGB trim says nothing about - FixtureProfilesModule: profileHasWhiteDie(), narrower than profileHasSynthChannel, so a profile carrying amber but no white does not offer a slider that changes nothing **Tests** - Six cases: one trim leaves the others untouched, a trim does not reach the white die, the curve and a trim compose into one table, whiteLevel moves the white alone, and whiteLevel of 0 puts the die out rather than leaving it at the never-black floor **Docs/CI** - The Shared driver card gains the four controls, with the reasoning in its details section Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
This fits the plan (linked in #138) as a picture source: a USB transport plus the P4's MJPEG decoder. Like #138, it stays open while I research the plan further; comments on the plan are very welcome. (As in my comment on #138: one topic per PR, roughly 400 lines and ten files, so each can be reviewed properly.) The color trim ("Trim each LED die…") is a separate idea from capture: output calibration, touching every board's LED output. I'm considering it on its own as well, and haven't decided on it yet. Two notes for when we get there: the brightness table is rebuilt 1280 times instead of 256 every 20 ms during the 5 s soft start, which filling the neutral row once and copying it would avoid; and the textbook form is a 3×3 correction matrix rather than three gains. Please hold off on updating this PR until I've done the groundwork; then we'll look together at where the capture fits, so no effort goes into a shape that changes. For reference only, the review points so far on the capture part:
Good work on the capture seam itself: the opaque handle, the generation counter and formats learned at enumeration are exactly the shape we want. |
|
One more note for future PRs: please branch each one from current main rather than from your previous PR's branch. #139 and #140 each carry the commits of the PRs before them (#140 shows 34 files for its own ~160 lines), so a review can't see one topic on its own, and a change in an earlier PR ripples into every later one. Only when one topic needs several steps should a step build on the one below it; it then gets reviewed once that one merges. |
A stream mapped by its sender (xLights, FSEQ, Network Send) now reaches the LEDs in one copy on any layout, halving the S3's tick at 64x64, and a modifier on its layer transforms it. A new Picture service and Picture effect show a test card on any layout, fitted, filled or stretched, ready for USB capture and a browser source to feed them. The installer resends settings the board refused, lets a mistyped WiFi password be corrected in place, and applies a device's defaults without reflashing. KPI: 256lights | Desktop:2326KB | tick:6/9/7/2/12/8/274/7/14/14us(FPS:166666/111111/142857/500000/83333/125000/3649/142857/71428/71428) | src:331(84711) | test:243(55778) | functions-over:353 Commit: src +820/-143 lines | test +659/-106 lines | duplicated lines 3654 -> 3654 (+0) **Core** - PictureFrame and PictureService (G3): a picture source in Audio's pattern, the PM5544 test card drawn at any size, a Reader that holds the picture for one gather, and two pictures swapped by pointer for a source writing from its own task, degrading to one locked picture when the second does not fit (the groundwork #139's USB capture lands on). - WiFi join window shared by NetworkModule and the Improv answer (JoinWindow.h): 10 s to join, plus 15 s for the lease once joined, so a slow router no longer drops a joined board to its access point, and a wrong password is reported in about 12 s instead of an installer timeout. - Platform: wifiStaAssociated() on ESP32, desktop and the no-WiFi stub; the USB-Serial-JTAG console moved onto the driver, so S3 and P4 boards log on their native USB port in the standard build. - ES7210 microphone codec beside the ES8311, behind a new MM_AUDIO_CODEC Kconfig gate (on for S31, P4 and the Waveshare ESP32-S3-RGB-Matrix image), so boards with an INMP441-style mic carry no codec library. **Light domain** - G5: Layer::wiringSource decides when a wiring-order frame goes straight to the output, and Drivers copies it there; on the S3 at 64x64 serpentine the tick fell from 5.83 to 2.96 ms. Under a static modifier the frame is placed by the layout's positions (Layer::placeByLayout), so a mirror or transpose transforms it. - G6: ChannelDataSink holds, places and copies channel data for Network Receive and the new FseqPlayerEffect, a registered stub with file, loop and speed that reads no file yet (TouchMyLight's contribution). - G4: PictureEffect samples the picture per light, fit, fill or stretch, point or area in linear light, from separable range tables refilled without allocating. - Drivers composites through one composite() helper; BeatRipples walks the whole palette, its index wrapping with height and shifting per stone. **UI** - Installer: stop-and-wait APPLY_OP that reads the board's replies and resends a refused or unanswered document; a WiFi form that comes back with the reason after a failed join; "Apply device defaults now, without flashing"; an erase progress bar estimated at 3 s per MB. - Tooltips for the picture and recorded-show emoji. - Waveshare ESP32-S3-RGB-Matrix device model: ES7210 audio and BeatRipples as its default effect. **Scripts/MoonDeck** - fseq_play: writes and plays uncompressed FSEQ v2 over DDP, the reference sender for FSEQ. - monitor_esp32 raises only the board on its port to Info, in the background, restores it on exit or SIGTERM, and opens the port without asserting DTR/RTS; collect_kpi raises only its own board and says when none is registered. - screenshot_modules lets the device name the modules it adds, which the 15-character name limit refused for long type names. **Tests** - G5: pass-through on serpentine and 3D layouts, a mirror and a transpose on sender-mapped frames, both failing with the placement switched off. - PictureService: the test card's landmarks, the generation, the empty frame, and a writer task racing a reader with two pictures and with one, both reading every picture whole (the one-picture case fails with its lock removed). - PictureEffect: point against area by hand, fit, fill and stretch, a cube, no resampling without a new picture; FseqPlayerEffect: its output path and status; BeatRipples: the palette spread; NetworkModule: the join window and a rejoin after a dropout; installer reply parsing. **Docs/CI** - Streams plan: G3 to G7 built, G8 (the browser as a picture source) added with recording and baking as follow-ups; the how-to for adding a picture or channel-data source (G7); cards and images for Picture, FseqPlayer and the new Network Receive card. - CLAUDE.md: every pull request is based on main, the one exception a step of a larger topic. **Reviews** - 👾 the background log-level raise could hold the port for about 75 s on an unreachable board: fixed, it stops with the monitor. - 👾 collect_kpi skipped a board with no recorded port silently: fixed, it says so. - 👾 wiringSource computed per frame: kept, since a state document that changes mapped_by re-prepares only the effect, so a cached answer would go stale. - 👾 any Improv error aborted the defaults push: fixed, only "unknown RPC" means unsupported, the rest is resent. - 👾 the two-picture writer path has no writer yet: accepted, it is #139's groundwork, built on request before this commit; the double generation bump in prepare fixed. - 👾 FseqPlayerEffect's default dimensions override and PictureEffect's unexplained include: fixed. - 🐇 CLAUDE.md's generated-file wording, the plan's pacing paragraph, a long test comment, an unsynchronized staging read in a test: fixed; the repo-health coverage count: not a defect, marker and summary share the n >= 4 threshold. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The groundwork for USB capture is now on main (#141), so here is what to build on. What is set up
What to do
The review points from my earlier comment still apply: no 3 s freeze without a grabber, the USB tasks on core 1, the UVC payload header length from its flags, the flash cost measured, and This PR can then close. The color trim is a separate idea and a separate PR whenever you want to take it up. Where to read
For the PR: one topic, based on current Your capture seam was the right shape from the start, and it now has a place to land. |
|
Thanks @Gohnnyman, closing this one: its capture half landed as the groundwork in #151, and the USB transport follows in the UVC PR you announced there. The color trims ( |
What's new
hdrdeclares the source curve (PQ / HLG), since MJPEG carries no metadata. Gated on the chip and both SoC capabilities; every other target links a failing stub.balanceRed/Green/Bluetrim a die down to correct a cast;whiteLeveltrims the white die, which the RGB trims cannot reach. Folded into the same table fill as the curve, so the hot path stays one lookup.Built for
esp32p4rev3-eth-wifi, which links the UVC driver, andesp32s3-n16r8, which links stubs and no component. Verified on a P4: capture, decode and the trims all live.Note
This PR is a part of #138 and #140
This PR Stacked on #138 , so that PR should be merged first