Repository navigation
Add HUB75 refresh rates by chain length and color depth - #230
Conversation
A reference page for sizing a HUB75 chain before wiring it: the refresh rate a chain reaches at 8, 11 and 16 bits per color, worked out from the shift clock, the bit planes and each plane's on-time, for panels driven from GPIO and for ColorLight 5A-75 receiving cards. **Docs/CI** - hub75-refresh.md: the formula with one worked example, how `rpi-rgb-led-matrix`, the ESP32 HUB75 driver and SmartMatrix each set the LSB, tables for 128x64 panels at 1/32 scan, and the ColorLight cards' specs and refresh ceilings, with sources. The ESP32 driver sits at the formula's ceiling: one shift per plane at its 20 MHz pixel clock, the latch riding the last pixel, which gives the 2,441 Hz its bench figure is measured against. The tables are recomputed from the formula and match. - mkdocs.yml: the page under Reference, Hardware, after HUB75 panels. - hub75-panels.md: the ESP32 bench figure links the page's ceiling in place of its own line-time formula, and points to the page for longer chains and deeper color. - panel-cards.md: links the card ceilings; "specialised" to "specialized"; the parts table names the card models in place of referring to the page itself, and section 8 is titled "When the wall stays dark", in positive form. - 06-advanced.yaml: the panel-card step links section 8 by its new heading. - check_prose: NegatedHeading 6 to 7 and project_mirror's 7 findings are main's baseline, outside this diff. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the
|
There was a problem hiding this comment.
🟡 Changes recommended
The guide contains unresolved inaccuracies in Pi PWM timing conversion, refresh-rate ceilings, and SmartMatrix’s achievable refresh rate and effective color depth.
4 open issues
What changed in this PR
Adds a HUB75 refresh-rate reference to help size panel chains by color depth, covering GPIO drivers and ColorLight receiving cards.
Changes:
- Documents timing formulas, a worked example, and refresh-rate and brightness tables.
- Adds the reference to site navigation and links it from existing hardware guides.
- Renames the receiving-card troubleshooting heading and updates its process link.
| File | Description |
|---|---|
moonwalk/06-advanced.yaml |
Updates the troubleshooting link to the renamed heading. |
mkdocs.yml |
Adds the refresh-rate page under Reference → Hardware. |
docs/reference/hardware/panel-cards.md |
Links card ceilings and refines wording and the troubleshooting heading. |
docs/reference/hardware/hub75-refresh.md |
Adds timing models, driver comparisons, sizing tables, and sources. |
docs/reference/hardware/hub75-panels.md |
Links the bench comparison and chain-sizing guidance to the new reference. |
Review effort: Balanced
| | t_latch | Latch and set-up time per shifted row | 0.5 µs | | ||
| | L | LSB time: how long the least significant plane stays lit | 130 ns, the `rpi-rgb-led-matrix` default, or 50 ns | | ||
|
|
||
| A real chain sits between the two bounds: its low planes are shift-bound and its high planes are on-time-bound. The ceiling falls as the chain grows. The on-time bound halves with each extra bit and stays the same at any chain length. |
|
|
||
| | Driver | What it holds fixed | What follows | Its highest rate | | ||
| |---|---|---|---| | ||
| | `rpi-rgb-led-matrix` | The LSB time, `--led-pwm-lsb-nanoseconds` | The refresh rate, from the formula | The formula's f, at up to 11 bit planes, `--led-pwm-bits` | |
| | 6 | 768 | 49,152 | 83 Hz | 366.4 ns | 25% | 83 Hz | 9% | 83 Hz | 3% | | ||
| | 8 | 1024 | 65,536 | 63 Hz | 487.2 ns | 25% | 63 Hz | 7% | 63 Hz | 3% | | ||
|
|
||
| At 8 bits the shift clock sets the rate, and a shorter LSB only dims the panel. |
| | 6 | 768 | 49,152 | 42 Hz | 1.4 ns | 12% | 3.5 Hz | 96% | 8.5 Hz | 89% | | ||
| | 8 | 1024 | 65,536 | 31 Hz | 1.9 ns | 12% | 3.5 Hz | 95% | 8.1 Hz | 85% | | ||
|
|
||
| A fixed LSB at 16 planes and 1/32 scan flickers at single-digit rates. SmartMatrix's 48-bit mode reaches 240 Hz on one panel with an LSB of 0.3 ns, well inside one timer tick, so its lowest planes share one on-time. |
|
Merged, thanks James! A careful page: the formula, a worked example and sourced tables, and the ESP32 bench figure now has a ceiling to be measured against. |
NdiDriver.h takes #227's per-light read by role. panel-cards.md and 06-advanced.yaml keep this branch's numbering, where "8. Set the card up in LEDVision" puts "When the wall stays dark" at 9. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…th, a sanitizer-clean seqlock The ESP32-P4's HDMI output no longer allocates on the render tick and frees its frame only once no write is in flight, as the desktop does; a refused output is opened again by itself. CI's thread-sanitizer job builds again, and the branch's merge losses and doc gaps are restored. KPI: 256lights | Desktop:2282KB | tick:7/10/8/2/8/7/270/7/7/11us(FPS:142857/100000/125000/500000/125000/142857/3703/142857/142857/90909) | src:353(91049) | test:266(62360) | functions-over:345 Commit: src +46/-19 lines | test +3/-11 lines | duplicated lines 3217 -> 3217 (+0) **Core** - ESP32 HDMI: the output task grows the frame (growFrame), the tick only asks; hdmiClose claims the frame slot before freeing it. - hdmi_handover.h: the seqlock reader closes with a read-don't-modify-write (Boehm's reader) instead of atomic_thread_fence, which GCC's -fsanitize=thread rejects; reproduced and verified with GCC 14 on the Pi. - platform.h forward-declares edid::Monitor instead of including the parser into every unit. **Light domain** - HdmiDriver: a refused output asks the scheduler for a prepare every 5 s; the scaling Select's values are named (kScalingFit, kScalingStretch). - NdiDriver: release() chains to DriverBase::release(), so a disabled NDI driver frees its staging. - EffectBase.h carries <algorithm>, AudioSpectrumEffect drops its second include. **Tests** - unit_ModuleContract: NdiDriver's two exemption rows removed, the lists only shrink. - unit_stop_signal gets its @module tag; test_check_docgen loses the test of the removed appendix filter. - The HDMI live scenario passes on the Olimex P4-PC (board B) with the ESP32 fixes flashed. **Scripts/MoonDeck** - check_docgen: the appendix-total filter goes; the committed baseline no longer carries that row. **Docs/CI** - panel-cards.md: three of #230's lines the merge of main had dropped are back (specialized, the 5A-75B or 5A-75E row, the HUB75 refresh rates link). - The platform page names RTSP and HDMI; the links to #218 say #218. - The ArtPoll discovery card states the send retries (Project card, mirror regenerated). - .coderabbit.yaml filters generated files, plans and images, so a PR's review fits CodeRabbit's 100-file limit. - help.json regenerated; the prose count falls to 2011. - Performance: Layers_stack_and_blend_live reads 270 us against 163 in main's last KPI (9302c9c); today's main measures the same as this branch (295-297 us on both, three runs each), so main moved in merges that recorded no KPI. **Reviews** - Reviewer: the ESP32 hdmiWrite allocates on the tick: done, the task grows it. - Reviewer: the ESP32 hdmiClose frees the frame without the slot: done, claimUnlessWriting. - Reviewer: the merge of main lost #230's link on panel-cards.md: done, with two more lost lines found and restored. - Reviewer: the LEDVision how-to sits on a reference page, not in MoonWalk: accepted, the product owner's decision that MoonWalk describes MoonLight's own processes. - Reviewer: NdiDriver::release skips the base: done. - Reviewer: bare 0 and 1 for the scaling Select: done. - Reviewer: "specialised": done. - Reviewer: the platform page lacks HDMI: done. - Reviewer: a refused ESP32 open leaves a sticky wrong error: done, retried every 5 s; untested, the unit bench has no scheduler. - Reviewer: unit_stop_signal has no @module: done. - Reviewer: <algorithm> as a second include: done. - Reviewer: the default mode is positional and kMaxModes equals the desktop's count: skipped, the unit test pins index 2 on both tables and a ninth mode is when kMaxModes grows. - Reviewer: the bridge control exists where no bridge reads back: skipped, the desktop stand-in tests the readout the ESP32 shows. - Reviewer: platform.h includes the EDID parser: done; moving mm::edid under mm::platform skipped, taste. - Reviewer: links to #218 named after items: done. - Reviewer: a dead appendix filter in check_docgen: done. - Reviewer: eight topics on one branch: skipped, breadth without coupling on the product owner's integration branch. - CodeRabbit (#222): the ArtPoll card overstated what a failed send costs: done, card text approved by the product owner. - CodeRabbit (#222): manual MoonWalk steps described as recorded: skipped, the page already narrows it to script steps. - CodeRabbit (#222): the Discord reader skips archived threads: skipped, it already pages the archived public threads. - CI: the thread-sanitizer job fails on the seqlock's fence: done. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

A reference page for sizing a HUB75 chain before wiring it: the refresh rate a chain reaches at 8, 11 and 16 bits per color, worked out from the shift clock, the bit planes and each plane's on-time, for panels driven from GPIO and for ColorLight 5A-75 receiving cards.
Docs
rpi-rgb-led-matrix, the ESP32 HUB75 driver and SmartMatrix each set the LSB, tables for 128x64 panels at 1/32 scan, and the ColorLight cards' specs and refresh ceilings, with sources. The ESP32 driver sits at the formula's ceiling: one shift per plane at its 20 MHz pixel clock, the latch riding the last pixel, which gives the 2,441 Hz its bench figure is measured against. The tables are recomputed from the formula and match.The Raspberry Pi rows name the library's own flags. Once the HUB75 Pi driver lands, a follow-up names its controls instead.
What an agent wrote: Claude Code (Opus) wrote this page and this text from my direction; I reviewed every line and vouch for it.
Tested: On this branch on macOS,
build_docs --strictbuilds the site with the page in the nav,check_specsandcheck_docgenpass, andcheck_prosefinds the added lines clean. I recomputed the GPIO tables from the formula and they match.Skipped checks:
🤖 Generated with Claude Code