120 lines
5.1 KiB
Markdown
120 lines
5.1 KiB
Markdown
# Neopixel Command Calculator — Web Components Library
|
|
|
|
## Overview
|
|
Engineering calculator for finding NeoPixel/addressable LED data transmission limits from single hardware sources. Ships as a CDN-ready Web Components library (Lit + Vite) that can be dropped into any JS app via `<script>` tag.
|
|
|
|
**Repo:** https://theres-a-git-in-this-tea.andrewawesomo.net/andrewadmin/neopixel-command-calculator
|
|
**First hardware profile:** ESP32-WROOM-32D
|
|
|
|
## Project Structure
|
|
```
|
|
neopixel-command-calculator/
|
|
├── index.html # Dev server demo
|
|
├── package.json / tsconfig.json / vite.config.ts / vitest.config.ts
|
|
├── src/
|
|
│ ├── index.ts # Entry point — exports + registers all components
|
|
│ ├── data/
|
|
│ │ ├── protocols.ts # WS2812B, SK6812, APA102, WS2811 timing specs
|
|
│ │ └── hardware-profiles.ts # ESP32-WROOM-32D (8 RMT channels, 2 SPI buses)
|
|
│ ├── engine/
|
|
│ │ ├── types.ts # TimingBreakdown, MaxLedsResult, StrandPlanResult, etc.
|
|
│ │ ├── timing.ts # Pure functions: calcDataTimeUs, calcMaxLeds, calcRefreshRate
|
|
│ │ └── strand-optimizer.ts # Multi-strand distribution across hardware channels
|
|
│ ├── components/
|
|
│ │ ├── max-leds.ts # <neopixel-max-leds>
|
|
│ │ ├── refresh-explorer.ts # <neopixel-refresh-explorer>
|
|
│ │ ├── strand-planner.ts # <neopixel-strand-planner>
|
|
│ │ └── shared/
|
|
│ │ ├── timing-bar.ts # Stacked bar chart (data | reset | idle)
|
|
│ │ ├── math-breakdown.ts # Expandable "show the math" section
|
|
│ │ └── styles.ts # CSS custom properties (--npc-accent, --npc-bg, etc.)
|
|
│ └── utils/
|
|
│ └── format.ts # Number/unit formatting helpers
|
|
└── test/
|
|
└── engine/
|
|
├── timing.test.ts
|
|
└── strand-optimizer.test.ts
|
|
```
|
|
|
|
## Three Calculator Components
|
|
|
|
### 1. `<neopixel-max-leds>` — Max LED Count Calculator
|
|
- **Inputs:** protocol, strand count, target refresh rate (Hz), hardware profile
|
|
- **Outputs:** max LEDs per strand, total LEDs, data rate utilization %, timing breakdown
|
|
- Shows the math: bit time x bits per LED x LED count vs available frame time
|
|
|
|
### 2. `<neopixel-refresh-explorer>` — Refresh Rate Explorer
|
|
- **Inputs:** LED count per strand, protocol, hardware profile
|
|
- **Outputs:** achievable refresh rates, timing budget visualization (bar chart: data | reset | idle)
|
|
- Interactive slider for LED count with real-time refresh rate updates
|
|
|
|
### 3. `<neopixel-strand-planner>` — Multi-Strand Planner
|
|
- **Inputs:** total LED count, protocol, hardware profile
|
|
- **Outputs:** optimal strand split across RMT/SPI channels, per-strand timing, aggregate refresh rate
|
|
- Shows which ESP32 pins/peripherals each strand uses
|
|
|
|
## Key Timing Math
|
|
|
|
### One-wire protocols (WS2812B, SK6812, WS2811)
|
|
```
|
|
frameBudgetUs = 1,000,000 / targetRefreshHz
|
|
maxLeds = floor((frameBudgetUs - resetTimeUs) / (bitsPerLed * bitPeriodNs / 1000))
|
|
```
|
|
|
|
**Example:** WS2812B at 30Hz:
|
|
- frameBudget = 33,333 us
|
|
- dataTimePerLed = 24 bits * 1250ns / 1000 = 30.0 us
|
|
- maxLeds = floor((33,333 - 50) / 30.0) = **1,109 LEDs**
|
|
|
|
### SPI protocols (APA102)
|
|
Clock-dependent, includes start/end frame overhead. At 8MHz SPI / 30Hz -> ~8,203 LEDs (raw timing).
|
|
|
|
### Multi-strand parallel output
|
|
All RMT channels transmit simultaneously. Aggregate refresh = 1M / max(frameTimeUs).
|
|
- 300 WS2812B on 3 strands -> 327Hz vs 110Hz single strand
|
|
|
|
## Protocol Data
|
|
|
|
| Protocol | Bits/LED | Bit Period (ns) | Reset (us) | Signal |
|
|
|---|---|---|---|---|
|
|
| WS2812B | 24 | 1250 | 50 | one-wire |
|
|
| SK6812 RGB | 24 | 1250 | 80 | one-wire |
|
|
| SK6812 RGBW | 32 | 1250 | 80 | one-wire |
|
|
| WS2811 800kHz | 24 | 1250 | 50 | one-wire |
|
|
| WS2811 400kHz | 24 | 2500 | 50 | one-wire |
|
|
| APA102 | 32 | varies (SPI clock) | 0 | spi |
|
|
|
|
## ESP32-WROOM-32D Hardware Profile
|
|
- 8 RMT channels (one-wire protocols, assignable to most GPIOs)
|
|
- 2 SPI buses: HSPI (GPIO 13), VSPI (GPIO 23) for APA102-style
|
|
- DMA-enabled operation assumed (ESP-IDF 4.4+)
|
|
- Default GPIO suggestions: 16, 17, 18, 19, 21, 22, 23, 25 for RMT
|
|
|
|
## Technology Stack
|
|
- **Framework:** Web Components via Lit 3.x
|
|
- **Build:** Vite library mode (ES + UMD bundles)
|
|
- **Language:** TypeScript
|
|
- **Testing:** Vitest for engine unit tests
|
|
- **Distribution:** CDN/script tag — single JS bundle, zero external deps for consumers
|
|
|
|
## Build Output
|
|
- `dist/neopixel-command-calculator.es.js` — ES module
|
|
- `dist/neopixel-command-calculator.umd.js` — UMD for `<script>` tag
|
|
- Lit bundled in (not a peer dep)
|
|
|
|
## Theming
|
|
CSS custom properties with `--npc-*` prefix. Consumers override at any ancestor level:
|
|
```css
|
|
neopixel-max-leds {
|
|
--npc-accent: #ff6b6b;
|
|
--npc-bg: #0d1117;
|
|
--npc-text: #e6edf3;
|
|
}
|
|
```
|
|
|
|
## Implementation Phases
|
|
1. **Foundation** — Data models, calculation engine, unit tests
|
|
2. **Shared UI** — CSS custom properties, timing-bar, math-breakdown, formatters
|
|
3. **Calculator Components** — All three components + dev server demo
|
|
4. **Build + Ship** — Vite library mode, UMD bundle test, push to Gitea
|