docs(readme): OLED section rewrite — 11 screens, new button model, web preview screenshots

- Bump screen count 10 → 11 in the OLED Display Add-on section to
  reflect the CPU/Clock screen added in v0.6.1.
- Update the cycle order to include CPU/Clock between Diagnostics and
  BT Signal.
- Drop the per-screen ASCII mockups (they were noisy and out of date)
  and link each screen section to a consistent web-preview screenshot
  under assets/oled/. Eleven screenshots, named oled_sc01.jpg through
  oled_sc11.jpg, captured from the OLED Preview tab of the web config
  so every screen looks the same and the chrome/layout matches the
  newly-flashed firmware.
- Rewrite the "KEY1 behavior by screen" table as a single "Button
  reference" table. K0 = next, K1 = back, K1 long-press = brightness
  cycle, K0+K1 hold = reboot. The per-screen state-change actions
  (Triangle / R1 / D-pad) live on the controller now and are
  documented per screen.
- Update Soft-reboot Recovery + the top-level Features bullet to
  reflect KEY0+KEY1 chord replacing KEY0 double-click.
- Update per-screen descriptions: Lightbar uses R1 to cycle mode (not
  K1); Trigger Test uses Triangle to cycle preset (not K1); Settings
  text updated to mention the new D-pad cursor behavior on the web
  preview.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
MarcelineVPQ
2026-05-18 22:11:16 -06:00
co-authored by Claude Opus 4.7
parent bd2f33bf0d
commit 5b9df0596b
12 changed files with 45 additions and 119 deletions
+45 -119
View File
@@ -47,7 +47,7 @@ This project enables the Raspberry Pi Pico2W to function as a Bluetooth bridge f
- **Lightbar color picker** with 4 user favorite slots + breathing / rainbow / fade effect presets - **Lightbar color picker** with 4 user favorite slots + breathing / rainbow / fade effect presets
- **Persistent settings menu** for the 8 firmware config fields (haptics gain, speaker volume, polling rate, etc.) with hold-to-confirm Reset and Wipe-all-slots actions - **Persistent settings menu** for the 8 firmware config fields (haptics gain, speaker volume, polling rate, etc.) with hold-to-confirm Reset and Wipe-all-slots actions
- **OLED brightness control + auto-dim** after 5 min idle (extends OLED life) - **OLED brightness control + auto-dim** after 5 min idle (extends OLED life)
- **Soft-reboot** without unplugging USB via DS5 `PS + Mute` hold (works headless) or OLED KEY0 double-click - **Soft-reboot** without unplugging USB via DS5 `PS + Mute` hold (works headless) or **KEY0 + KEY1 held together for 1 s** on the OLED add-on (replaces the older KEY0 double-click gesture, which was easy to fire by accident while paging quickly)
- **Audit pass on the core bridge** — critical stack-overflow fix in the audio path (resolves long-standing "audio stuttering"), security hardening, watchdog, length validation across HID/L2CAP boundaries (see [CHANGELOG.md](./CHANGELOG.md)) - **Audit pass on the core bridge** — critical stack-overflow fix in the audio path (resolves long-standing "audio stuttering"), security hardening, watchdog, length validation across HID/L2CAP boundaries (see [CHANGELOG.md](./CHANGELOG.md))
## Hardware ## Hardware
@@ -191,53 +191,25 @@ If you plug a [Waveshare Pico-OLED-1.3](#hardware) onto the Pico2W's headers, th
### Boot splash (1.5 s on power-on) ### Boot splash (1.5 s on power-on)
``` Centered firmware version on a blank screen for 1.5 seconds, then jumps to the Status screen.
┌──────────────────────────────┐
│ │
│ DS5 Bridge │
│ Pico2W + OLED │
│ │
└──────────────────────────────┘
```
### Ten screens, cycled with KEY0 on the add-on ### Eleven screens, cycled with KEY0 on the add-on
Cycle order: **Status → Slots → Lightbar → Trigger Test → Gyro Tilt → Touchpad → Diagnostics → RSSI → VU Meters → Settings →** wrap. KEY0 short-press steps forward. KEY1 short-press steps backward (with two contextual exceptions, see the table at the end). Cycle order: **Status → Slots → Lightbar → Trigger Test → Gyro Tilt → Touchpad → Diagnostics → CPU/Clock → BT Signal → VU Meters → Settings →** wrap. **KEY0 short-press steps forward; KEY1 short-press steps backward** — on *every* screen. Per-screen interactions (cycling the trigger preset, cycling the lightbar mode, navigating the Settings cursor, switching slots) live on the **DualSense controller buttons**, never on KEY0/KEY1, so the two physical buttons on the OLED add-on always mean the same thing.
Every screen also paints **`>`** at the top-left edge (next to KEY0) and **`<`** at the bottom-left edge (next to KEY1) so the on-screen labels physically pair with the buttons.
#### 1. Status #### 1. Status
Connection state, paired DualSense BD address, battery % with bar (`+` charging / `*` complete / `!` error), live analog stick positions, D-pad, face buttons (△ ◯ ✕ □), L1/R1, and L2/R2 analog trigger fill bars. The link indicator and battery use small pixel icons. Connection state, paired DualSense BD address, battery % with bar (`+` charging / `*` complete / `!` error), live analog stick positions, D-pad, face buttons (△ ◯ ✕ □), L1/R1, and L2/R2 analog trigger fill bars. The link indicator and battery use small pixel icons.
``` <img src="./assets/oled/oled_sc01.jpg" alt="Status screen on the OLED" width="420">
┌──────────────────────────────┐
│ DS5 Bridge v0.6.0 ● │
│ 14:3A:9A:FF:D9:F9 │
│ 87%+ ╔══════════════╗ │
│ ║██████░░░░░░░░║▌ │
│ ┌────┐ L1 △ R1 ┌────┐│
│ │ ·• │ L2 ○ □ R2 │ ·• ││
│ │ │ ▌ ✕ ▌ │ ││
│ └────┘ └────┘│
└──────────────────────────────┘
```
<img src="./assets/main_screen_01.jpeg" alt="Status screen on the OLED" width="420">
#### 2. Slots #### 2. Slots
Persistent 4-slot multi-controller pairing. Browse stored controllers, switch active slot, or wipe a single slot. `>` is the cursor, `*` marks the currently active slot. Persistent 4-slot multi-controller pairing. Browse stored controllers, switch active slot, or wipe a single slot. `>` is the cursor, `*` marks the currently active slot.
``` <img src="./assets/oled/oled_sc02.jpg" alt="Slots screen on the OLED" width="420">
┌──────────────────────────────┐
│ Slots [s0 ON] │
│ >0* 14:3A:9A:FF:D9:F9 │
│ 1 (empty) │
│ 2 (empty) │
│ 3 (empty) │
│ │
│ Tri=switch Sq hold=wipe │
└──────────────────────────────┘
```
- **D-pad ▲▼** — move cursor across slots 03 - **D-pad ▲▼** — move cursor across slots 03
- **△** — switch to the cursor slot (disconnect current, reconnect to slot's stored controller) - **△** — switch to the cursor slot (disconnect current, reconnect to slot's stored controller)
@@ -248,42 +220,17 @@ Persistent 4-slot multi-controller pairing. Browse stored controllers, switch ac
Tilt the controller on each axis to dial in R / G / B; the firmware sends the resulting color to the DualSense's actual lightbar at 10 Hz, so the lightbar IS the visual preview (the OLED is monochrome). Tilt the controller on each axis to dial in R / G / B; the firmware sends the resulting color to the DualSense's actual lightbar at 10 Hz, so the lightbar IS the visual preview (the OLED is monochrome).
``` <img src="./assets/oled/oled_sc03.jpg" alt="Lightbar color picker on the OLED" width="420">
┌──────────────────────────────┐
│ Lightbar [LIVE] │
│ R:128 G: 77 B:200 │
│ ████░░░ ██░░░░░ ██████░░ │
│ (R) (G) (B) │
│ Sv: T=0 C=1 X=2 S=3 │
│ Tilt = R/G/B │
│ K0=next K1=cycle │
└──────────────────────────────┘
```
<img src="./assets/lightbar_01.jpeg" alt="Lightbar color picker on the OLED" width="420">
- Press **△ ◯ ✕ □** on the controller to **save** the current color into favorite slot 0 / 1 / 2 / 3 - Press **△ ◯ ✕ □** on the controller to **save** the current color into favorite slot 0 / 1 / 2 / 3
- Press **KEY1** to cycle the mode tag: `[LIVE]` → `[FAV0]` → `[FAV1]` → `[FAV2]` → `[FAV3]` → effects (Breathing / Rainbow / Fade) → back to `[LIVE]` - Press **R1** on the controller to cycle the mode tag: `[LIVE]` → `[FAV0]` → `[FAV1]` → `[FAV2]` → `[FAV3]` → effects (Breathing / Rainbow / Fade) → back to `[LIVE]`
- Default favorites: Red, Green, Blue, White - Default favorites: Red, Green, Blue, White
#### 4. Trigger Test #### 4. Trigger Test
KEY1 cycles seven adaptive trigger effects applied to both L2 and R2. Pull each trigger to feel the effect. Press **△** on the controller to cycle seven adaptive trigger effects applied to both L2 and R2. Pull each trigger to feel the effect.
``` <img src="./assets/oled/oled_sc04.jpg" alt="Trigger Test screen on the OLED" width="420">
┌──────────────────────────────┐
│ Trigger Test │
│ Mode: Weapon │
│ L2: 127 R2: 42 │
│ │
│ ████░░░░░░ ██░░░░░░░░ │
│ (L2 pull) (R2 pull) │
│ │
│ K0=next K1=cycle │
└──────────────────────────────┘
```
<img src="./assets/triggertest_01.jpeg" alt="Trigger Test screen on the OLED" width="420">
Cycle order: **Off → Feedback → Weapon → Vibration → Bow → Gallop → Machine Gun → Off …** Effect parameters bitpacked per [dualsensectl](https://github.com/nowrep/dualsensectl)'s reverse-engineering, all at max strength. Cycle order: **Off → Feedback → Weapon → Vibration → Bow → Gallop → Machine Gun → Off …** Effect parameters bitpacked per [dualsensectl](https://github.com/nowrep/dualsensectl)'s reverse-engineering, all at max strength.
@@ -291,69 +238,45 @@ Cycle order: **Off → Feedback → Weapon → Vibration → Bow → Gallop →
Live X/Y/Z accelerometer values with a 40×40 crosshair box. Tilt the controller and the dot tracks in real time. Live X/Y/Z accelerometer values with a 40×40 crosshair box. Tilt the controller and the dot tracks in real time.
``` <img src="./assets/oled/oled_sc05.jpg" alt="Gyro Tilt screen on the OLED" width="420">
┌──────────────────────────────┐
│ Gyro Tilt │
│ X +123 Y -456 Z +8123 │
│ ┌────────┐ │
│ │ │ │ │
│ │───•────│ │
│ │ │ │ │
│ └────────┘ │
└──────────────────────────────┘
```
<img src="./assets/gyro_tilt_01.jpeg" alt="Gyro Tilt screen on the OLED" width="420">
#### 6. Touchpad #### 6. Touchpad
Live render of the touchpad surface. Dots appear at current finger positions; the count updates as fingers touch / leave. Live render of the touchpad surface. Dots appear at current finger positions; the count updates as fingers touch / leave.
``` <img src="./assets/oled/oled_sc06.jpg" alt="Touchpad screen on the OLED" width="420">
┌──────────────────────────────┐
│ Touchpad │
│ ┌──────────────────────────┐ │
│ │ • • │ │
│ │ │ │
│ └──────────────────────────┘ │
│ Fingers: 2 │
│ │
│ K0=next │
└──────────────────────────────┘
```
<img src="./assets/touchpad_01.jpeg" alt="Touchpad screen on the OLED" width="420">
#### 7. Diagnostics #### 7. Diagnostics
Uptime, BT state, and stub counters for HCI errors / audio FIFO drops / opus FIFO drops (always 0 in this build — kept for future wiring). Uptime, BT state, USB-audio frames/sec, BT 0x32 packets/sec, and HCI error counter — live values for verifying the audio path is moving bytes without needing a UART cable.
``` <img src="./assets/oled/oled_sc07.jpg" alt="Diagnostics screen on the OLED" width="420">
┌──────────────────────────────┐
│ Diagnostics │
│ Up: 0h 14m 22s │
│ HCI errs: 0 │
│ Aud drops: 0 │
│ Opus drops: 0 │
│ BT: connected │
│ │
│ K0=next │
└──────────────────────────────┘
```
<img src="./assets/diagnostics_01.jpeg" alt="Diagnostics screen on the OLED" width="420"> #### 8. CPU / Clock
#### 8. RSSI Live RP2350 vitals: configured (`Set`) and actually-running (`Real`) system clock measured against the crystal reference, core voltage read back from the regulator, and on-die temperature (256-sample average + slow EMA so the value tracks the real die temp rather than ADC noise).
Live Bluetooth signal strength of the active link, in dBm with a bar. Closer to 0 dBm is stronger; 90 dBm is weak. <img src="./assets/oled/oled_sc08.jpg" alt="CPU / Clock diagnostics screen on the OLED" width="420">
#### 9. VU Meters The same telemetry is also exported on HID feature report `0xFC` for tooling.
#### 9. BT Signal
Live Bluetooth signal strength of the active link, in dBm with a bar. Closer to 0 dBm is stronger; 90 dBm is weak. Includes a qualitative label (Poor / Fair / Good / Excellent).
<img src="./assets/oled/oled_sc09.jpg" alt="BT Signal screen on the OLED" width="420">
#### 10. VU Meters
Live peak meters for the speaker and haptic audio paths. Useful for verifying audio routing without the controller being plugged in to a host. Live peak meters for the speaker and haptic audio paths. Useful for verifying audio routing without the controller being plugged in to a host.
#### 10. Settings <img src="./assets/oled/oled_sc10.jpg" alt="VU Meters screen on the OLED" width="420">
Persistent config editor. D-pad ▲▼ moves the selection, ▶◀ adjusts values, △ saves to flash. Includes the 8 firmware-config fields (haptics gain, speaker volume, inactive timeout, etc.), the Audio Auto Haptics controls, and two hold-to-confirm actions: #### 11. Settings
Persistent config editor. D-pad ▲▼ moves the selection, ▶◀ adjusts values, △ saves to flash. Includes the firmware-config fields (haptics gain, speaker volume, inactive timeout, polling rate), the Audio Auto Haptics controls, and two hold-to-confirm actions:
<img src="./assets/oled/oled_sc11.jpg" alt="Settings screen on the OLED" width="420">
- **AutoHap Off / Fallback / Mix / Replace** — selects the Audio Auto Haptics mode. Default `Fallback` fires derived rumble only when the game sends no native haptic data (e.g. Ghost of Tsushima on Linux); games that *do* send native haptics (Spider-Man Remastered) pass through unchanged. `Mix` adds derived on top of native, `Replace` ignores native entirely, `Off` disables. - **AutoHap Off / Fallback / Mix / Replace** — selects the Audio Auto Haptics mode. Default `Fallback` fires derived rumble only when the game sends no native haptic data (e.g. Ghost of Tsushima on Linux); games that *do* send native haptics (Spider-Man Remastered) pass through unchanged. `Mix` adds derived on top of native, `Replace` ignores native entirely, `Off` disables.
- **AH Gain N%** — derived-signal gain, 0200 % in 10 % steps. Default 100 %. - **AH Gain N%** — derived-signal gain, 0200 % in 10 % steps. Default 100 %.
@@ -361,15 +284,18 @@ Persistent config editor. D-pad ▲▼ moves the selection, ▶◀ adjusts value
- **Reset to defaults** — hold △ for 2 s to revert all config fields - **Reset to defaults** — hold △ for 2 s to revert all config fields
- **Wipe all slots** — hold △ for 2 s to drop all 4 paired controllers + all BTstack link keys - **Wipe all slots** — hold △ for 2 s to drop all 4 paired controllers + all BTstack link keys
### KEY1 behavior by screen ### Button reference
| Screen | KEY1 short-press action | The two physical buttons on the OLED add-on are **strictly navigation**:
| Button | Action |
|---|---| |---|---|
| Status, Slots, Gyro Tilt, Touchpad, Diagnostics, RSSI, VU Meters, Settings | Step **backward** one screen (mirror of KEY0's forward step) | | **KEY0** short-press | Next screen (forward) |
| Trigger Test | Cycle the trigger effect preset | | **KEY1** short-press | Previous screen (backward) |
| Lightbar Color Picker | Cycle between LIVE preview, the 4 favorite slots, and the effect presets | | **KEY1** long-press (≥ 1.5 s) | Cycle OLED brightness level |
| **KEY0 + KEY1** held together ≥ 1 s | `watchdog_reboot` — soft-reboot without unplugging USB |
KEY1 long-press (≥1.5 s) on any screen cycles the OLED brightness level. Per-screen state changes (cycling the trigger preset, cycling the lightbar mode, navigating Settings, switching slots, saving colors to favorite slots) all happen on the **DualSense controller buttons** — never on KEY0 / KEY1 — so the two physical buttons always mean the same thing across every screen. See each screen's section above for which controller button does what.
### Pinout (standard Waveshare Pico HAT layout) ### Pinout (standard Waveshare Pico HAT layout)
@@ -387,8 +313,8 @@ KEY1 long-press (≥1.5 s) on any screen cycles the OLED brightness level.
Two ways to reboot the dongle without unplugging USB — handy if pairing gets stuck or you want a clean state: Two ways to reboot the dongle without unplugging USB — handy if pairing gets stuck or you want a clean state:
- **OLED KEY0 double-click** within ~400 ms → `watchdog_reboot` - **OLED KEY0 + KEY1 held simultaneously for ≥ 1 s** → `watchdog_reboot`. Replaces the older "KEY0 double-click" gesture from earlier versions, since rapid forward-navigation kept tripping the double-click timer by accident.
- **DualSense `PS + Mute` held for 2 seconds** → `watchdog_reboot` (works whether or not the OLED is attached) - **DualSense `PS + Mute` held for 2 seconds** → `watchdog_reboot` (works whether or not the OLED is attached — headless backup).
## Acknowledgements ## Acknowledgements
Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB