diff --git a/README.md b/README.md index 4deddfd..33dcffa 100644 --- a/README.md +++ b/README.md @@ -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 - **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) -- **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)) ## 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) -``` -┌──────────────────────────────┐ -│ │ -│ DS5 Bridge │ -│ Pico2W + OLED │ -│ │ -└──────────────────────────────┘ -``` +Centered firmware version on a blank screen for 1.5 seconds, then jumps to the Status screen. -### 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 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. -``` -┌──────────────────────────────┐ -│ DS5 Bridge v0.6.0 ● │ -│ 14:3A:9A:FF:D9:F9 │ -│ 87%+ ╔══════════════╗ │ -│ ║██████░░░░░░░░║▌ │ -│ ┌────┐ L1 △ R1 ┌────┐│ -│ │ ·• │ L2 ○ □ R2 │ ·• ││ -│ │ │ ▌ ✕ ▌ │ ││ -│ └────┘ └────┘│ -└──────────────────────────────┘ -``` - -Status screen on the OLED +Status screen on the OLED #### 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. -``` -┌──────────────────────────────┐ -│ Slots [s0 ON] │ -│ >0* 14:3A:9A:FF:D9:F9 │ -│ 1 (empty) │ -│ 2 (empty) │ -│ 3 (empty) │ -│ │ -│ Tri=switch Sq hold=wipe │ -└──────────────────────────────┘ -``` +Slots screen on the OLED - **D-pad ▲▼** — move cursor across slots 0–3 - **△** — 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). -``` -┌──────────────────────────────┐ -│ 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 │ -└──────────────────────────────┘ -``` - -Lightbar color picker on the OLED +Lightbar color picker on the OLED - 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 #### 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. -``` -┌──────────────────────────────┐ -│ Trigger Test │ -│ Mode: Weapon │ -│ L2: 127 R2: 42 │ -│ │ -│ ████░░░░░░ ██░░░░░░░░ │ -│ (L2 pull) (R2 pull) │ -│ │ -│ K0=next K1=cycle │ -└──────────────────────────────┘ -``` - -Trigger Test screen on the OLED +Trigger Test screen on the OLED 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. -``` -┌──────────────────────────────┐ -│ Gyro Tilt │ -│ X +123 Y -456 Z +8123 │ -│ ┌────────┐ │ -│ │ │ │ │ -│ │───•────│ │ -│ │ │ │ │ -│ └────────┘ │ -└──────────────────────────────┘ -``` - -Gyro Tilt screen on the OLED +Gyro Tilt screen on the OLED #### 6. Touchpad Live render of the touchpad surface. Dots appear at current finger positions; the count updates as fingers touch / leave. -``` -┌──────────────────────────────┐ -│ Touchpad │ -│ ┌──────────────────────────┐ │ -│ │ • • │ │ -│ │ │ │ -│ └──────────────────────────┘ │ -│ Fingers: 2 │ -│ │ -│ K0=next │ -└──────────────────────────────┘ -``` - -Touchpad screen on the OLED +Touchpad screen on the OLED #### 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. -``` -┌──────────────────────────────┐ -│ Diagnostics │ -│ Up: 0h 14m 22s │ -│ HCI errs: 0 │ -│ Aud drops: 0 │ -│ Opus drops: 0 │ -│ BT: connected │ -│ │ -│ K0=next │ -└──────────────────────────────┘ -``` +Diagnostics screen on the OLED -Diagnostics screen on the OLED +#### 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. +CPU / Clock diagnostics screen on the OLED -#### 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). + +BT Signal screen on the OLED + +#### 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. -#### 10. Settings +VU Meters screen on the OLED -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: + +Settings screen on the OLED - **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, 0–200 % 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 - **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) | -| Trigger Test | Cycle the trigger effect preset | -| Lightbar Color Picker | Cycle between LIVE preview, the 4 favorite slots, and the effect presets | +| **KEY0** short-press | Next screen (forward) | +| **KEY1** short-press | Previous screen (backward) | +| **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) @@ -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: -- **OLED KEY0 double-click** within ~400 ms → `watchdog_reboot` -- **DualSense `PS + Mute` held for 2 seconds** → `watchdog_reboot` (works whether or not the OLED is attached) +- **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 — headless backup). ## Acknowledgements diff --git a/assets/oled/oled_sc01.jpg b/assets/oled/oled_sc01.jpg new file mode 100644 index 0000000..74bb1eb Binary files /dev/null and b/assets/oled/oled_sc01.jpg differ diff --git a/assets/oled/oled_sc02.jpg b/assets/oled/oled_sc02.jpg new file mode 100644 index 0000000..b468641 Binary files /dev/null and b/assets/oled/oled_sc02.jpg differ diff --git a/assets/oled/oled_sc03.jpg b/assets/oled/oled_sc03.jpg new file mode 100644 index 0000000..afb14e3 Binary files /dev/null and b/assets/oled/oled_sc03.jpg differ diff --git a/assets/oled/oled_sc04.jpg b/assets/oled/oled_sc04.jpg new file mode 100644 index 0000000..61b7901 Binary files /dev/null and b/assets/oled/oled_sc04.jpg differ diff --git a/assets/oled/oled_sc05.jpg b/assets/oled/oled_sc05.jpg new file mode 100644 index 0000000..2a581d6 Binary files /dev/null and b/assets/oled/oled_sc05.jpg differ diff --git a/assets/oled/oled_sc06.jpg b/assets/oled/oled_sc06.jpg new file mode 100644 index 0000000..ec50e32 Binary files /dev/null and b/assets/oled/oled_sc06.jpg differ diff --git a/assets/oled/oled_sc07.jpg b/assets/oled/oled_sc07.jpg new file mode 100644 index 0000000..d4d72b5 Binary files /dev/null and b/assets/oled/oled_sc07.jpg differ diff --git a/assets/oled/oled_sc08.jpg b/assets/oled/oled_sc08.jpg new file mode 100644 index 0000000..909cff6 Binary files /dev/null and b/assets/oled/oled_sc08.jpg differ diff --git a/assets/oled/oled_sc09.jpg b/assets/oled/oled_sc09.jpg new file mode 100644 index 0000000..d58bc0b Binary files /dev/null and b/assets/oled/oled_sc09.jpg differ diff --git a/assets/oled/oled_sc10.jpg b/assets/oled/oled_sc10.jpg new file mode 100644 index 0000000..7831540 Binary files /dev/null and b/assets/oled/oled_sc10.jpg differ diff --git a/assets/oled/oled_sc11.jpg b/assets/oled/oled_sc11.jpg new file mode 100644 index 0000000..086c8ce Binary files /dev/null and b/assets/oled/oled_sc11.jpg differ