Files
portal/README.md
Jimmy 5094c7bcee Add portal web simulator, SPI bridges, and Pico firmware updates.
Bring the five-panel hex portal online with a browser 3D/schematic preview, Pi SPI backends, and renamed multi-panel Pico UDP firmware.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-30 14:54:51 +12:00

138 lines
5.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# portal
Hexagonal LED portal: five WS2812 matrix panels on Pico UDP adapters, plus a bare floor.
Reference: [photo of the physical portal](https://technical.kiwi/images/portal/IMG_20241029_220222.jpg) — upright flat-top hex arch, dark frame, red LED grids on each face.
```
___[2]___
/ \
[1] [3]
| |
[0] [4]
\___________/
floor
```
WS2812 control for Raspberry Pi 5 (orchestrator) and Pico panel adapters.
## Panel IPs
Five Pico panels on `10.1.1.10``10.1.1.14`. Examples drive **all 5** by default.
## Panel sizes
Panels are **9 rows** tall; width varies by panel. Edit `PANEL_WIDTH_BY_INDEX` in `leds/array_config.py`:
| Panel | Face | IP | Size | LEDs | Firmware |
|-------|------|-----|------|------|----------|
| 0 | bottom-left | 10.1.1.10 | 9×39 | 351 | `make deploy PANEL_ID=0` |
| 1 | top-left | 10.1.1.11 | 9×45 | 405 | `make deploy PANEL_ID=1` |
| 2 | **top** | 10.1.1.12 | 9×45 | 405 | `make deploy PANEL_ID=2` |
| 3 | top-right | 10.1.1.13 | 9×45 | 405 | `make deploy PANEL_ID=3` |
| 4 | bottom-right | 10.1.1.14 | 9×39? | 351 | `make deploy PANEL_ID=4` |
Panels **0→1→2→3→4** run clockwise from bottom-left (`PORTAL_PANEL_ORDER_CLOCKWISE` in `leds/array_config.py`).
Panel 4 may be **38 or 39** wide — find the exact width:
```bash
make deploy PANEL_ID=4
pipenv run python examples/panel_sync_test.py --test width --panel-index 4
```
Last column that lights → set `PANEL_WIDTH_BY_INDEX[4]` in `leds/array_config.py` to **column + 1** (342 LEDs for 38, 351 for 39). Firmware takes pixel count from each UDP frame — no re-flash for width changes.
Animations render at each panel's own width automatically.
## Examples
### Portal web simulator
Preview all five panels in the browser (3D interior view + flat layout map). Uses the same Python animations as the hardware.
```bash
pipenv install fastapi "uvicorn[standard]"
pipenv run python examples/portal_simulator.py
# open http://localhost:8765/
```
Dev mode (default): **uvicorn reload** for Python changes, **browser auto-reload** when `web/` files change. Disable with `--no-reload` or `--no-browser-reload`.
Options: `--host 0.0.0.0 --port 8765` to view from another device on the network.
Open via the simulator URL (`http://…:8765/`) — do not open `index.html` directly from the filesystem (`file://`), or module imports will fail.
Frontend uses **Web Components** and ES modules under `web/js/`:
| Module | Role |
|--------|------|
| `<portal-app>` | Root layout, frame streaming |
| `<portal-controls>` | Sidebar settings |
| `<portal-viewport>` | Three.js 3D scene |
| `<portal-schematic>` | Flat layout map |
| `<portal-panel>` | Single LED matrix canvas |
### Pico panel (UDP)
WS2812 defaults: **GP28** (strip 0) and **GP27** (strip 1). Override over UDP:
```bash
pipenv run python examples/panel_color_test.py --panel-index 0 --pins 28:405,27:351
```
| Command | What it does |
|---------|----------------|
| `pipenv run python examples/panel_rgb_cycle.py` | Red / green / blue on all 5 panels |
| `pipenv run python examples/panel_color_test.py` | One-shot RGB + white test |
| `pipenv run python examples/panel_test.py` | Layout tests (corners, rows, chase) |
| `pipenv run python examples/panel_sync_test.py` | Positioning + sync across all panels |
| `pipenv run python examples/panel_animations.py` | All animations on all panels |
| `pipenv run python examples/panel_animations.py rolling` | One animation |
| `pipenv run python examples/panel_text.py` | Show your name |
| `pipenv run python examples/animations.py --panel` | Same as panel_animations |
Single panel only:
```bash
pipenv run python examples/panel_animations.py --panel-index 1 # 9×45 @ 10.1.1.11
```
### Pi SPI (bench / single matrix)
Optional local SPI tests via [`rpi5-ws2812`](https://github.com/niklasr22/rpi5-ws2812) on GPIO 10 — not used for the five portal panels.
405 LEDs need a ~10 KiB SPI frame. Default `spidev` bufsiz (4096) only updates ~169 LEDs — run once:
```bash
pipenv run python examples/setup_spi_bufsiz.py --install # sudo
```
| Command | What it does |
|---------|----------------|
| `pipenv run python examples/spi_rgb_test.py` | Red / green / blue over SPI |
| `pipenv run python examples/spi_panel_test.py` | Corners, rows, chase — verify all LEDs |
| `pipenv run python examples/animations.py` | All animations on local matrix |
| `pipenv run python examples/matrix_demo.py` | Rainbow only |
| `pipenv run python examples/led_demo.py` | Dual-strip chase + rainbow |
Colors use logical **RGB** everywhere (`(255,0,0)` = red). Pico firmware remaps to **GRB** on the wire; Pi SPI uses the same swap when needed. The web simulator stays logical RGB.
```python
# MicroPython on Pico — this is the reference:
np.fill((255, 0, 0)); np.write() # red
```
```bash
pipenv run python examples/panel_rgb_cycle.py # same colors over UDP
```
### Firmware
Pico SDK sources live under `firmware/pico/` (see that README for the UDP protocol).
```bash
make deploy PANEL_ID=0
make reset && make monitor
```