Add OpenDisplay Bluetooth LE e-paper output target

#1 · open · 0 comments

View on GitHub ↗

dotMorten

## Summary Add OpenDisplay as a Bluetooth Low Energy (BLE) output target so SideKick can render to battery-powered nRF52840 e-paper devices instead of requiring the current FT232H-to-USB display path. OpenDisplay is an open BLE e-paper protocol and reference firmware for nRF52840 and ESP32 boards. It exposes a BLE GATT service/characteristic (`00002446-0000-1000-8000-00805f9b34fb`) and supports compressed full-frame uploads plus capability-dependent monochrome partial updates. ## Why - Enable cable-free, battery-powered SideKick displays. - Allow small low-power e-paper tags/panels to be placed independently of the Windows host. - Keep the current FT232H hardware target fully supported while adding a second transport. This should be considered a new display target, not a replacement for FT232H. ## Existing architecture and opportunity The renderer already produces packed `EPaperFrame` instances (1 bpp, MSB-first) and computes changed regions in `ReconnectingDisplayTarget`. This packing is compatible with OpenDisplay's monochrome row-major/MSB-first image format. The hardware connection path is currently FT232H-specific: - `EPaperDisplayInfo.CreateDisplay` requires `Ft232HConnection` and pin mappings. - `ReconnectingDisplayTarget` creates/disposes FT232H connections, constructs FT232H-backed panel drivers, and owns the reconnect loop. - Display settings and the settings UI select an FT232H serial number. - The physical buttons are read through FT232H GPIO. Refactor the transport/connection concern away from panel geometry and rendering, retaining the existing FT232H target unchanged. ## Proposed scope ### Phase 1: Supported-device proof of concept - Add an OpenDisplay BLE GATT client for Windows/.NET. - Discover/select a device by stable BLE identity (address/device ID), connect, subscribe to notifications, and reconnect with backoff. - Read OpenDisplay device configuration/capabilities and validate: - panel dimensions; - monochrome color scheme; - full and partial refresh support; - required protocol/firmware version. - Transfer SideKick's transformed `EPaperFrame` as a compressed full-frame image. - Start with the simple/direct image-upload path; use protocol responses and timeouts rather than assuming writes succeed. - Preserve the latest successfully presented frame and require a full upload after reconnect, orientation change, capability change, or display-side state loss. ### Phase 2: Efficient partial updates - Map `EPaperFrameDiff` regions to OpenDisplay partial-update rectangles. - Honor OpenDisplay requirements: monochrome-only support, 8-pixel horizontal alignment, etag/state validation, and device-declared full-frame partial behavior. - Fall back to a full frame when partial updates are unsupported, rejected, stale, or cannot be safely represented. - Use the newer streaming/PIPE_WRITE protocol when it is negotiated and tested; retain compatibility fallback for supported older firmware. ### Phase 3: Settings and optional input - Introduce a display connection type/target selector so a user can choose FT232H or OpenDisplay BLE. - Add BLE discovery/refresh, selected-device persistence, connection status, capabilities, and actionable errors to the settings window. - Do not assume FT232H GPIO buttons exist for BLE devices. Add OpenDisplay button/input support only if the device advertises it and the host-side event model is well-defined. ## Power and behavior constraints The battery-life benefit is real only with a battery-focused update policy. SideKick currently renders on minute ticks, provider changes, calendar boundaries, and flashes per second during the final minute before an appointment. The per-second animation and frequent panel refreshes are incompatible with a year-scale battery objective on most e-paper hardware. For a 2,000 mAh battery to last one year, the complete device must average roughly 228 microamps. Panel refresh energy, rail leakage, advertising/connection intervals, and cold panel initialization all count toward that budget. OpenDisplay's current nRF52840 reference firmware is BLE-always-available and documents no deep-sleep path for the nRF target. Therefore this feature should: - default to full refreshes only when necessary; - use partial refresh only when device capability and panel behavior allow it; - provide a BLE/battery-friendly rendering policy that disables or coalesces per-second flashing; - avoid keeping the panel powered merely for host convenience; - document that battery life is hardware, panel, capacity, advertising interval, and update-frequency dependent rather than guaranteed by BLE alone. ## Hardware compatibility Start with a known OpenDisplay-compatible monochrome nRF52840 panel/board. The currently selected SideKick panel is a 1360x480 Good Display GDEM1085T41 dual-controller panel (81,600-byte 1-bit frame). OpenDisplay support for that exact panel/controller combination must be verified before claiming compatibility. If it is unsupported, support would require custom board wiring/power design and an OpenDisplay firmware/config/driver port; it should not block support for known-compatible devices. ## Security and reliability - Support OpenDisplay's optional encrypted device session/key configuration without storing keys in plaintext; use the existing protected-secret storage pattern. - Validate GATT service/characteristic identity and device-reported configuration before transmitting frames. - Serialize all per-device commands and handle notification loss, disconnects, protocol NACKs, image-transfer timeouts, and stale etags explicitly. - Do not silently continue after a failed refresh; retain reconnect behavior and force a known-good full refresh after recovery. ## Acceptance criteria - [ ] Existing FT232H display behavior, settings, preview rendering, and button input remain unchanged. - [ ] A supported OpenDisplay monochrome BLE device can be selected from the settings UI and receives a full SideKick frame. - [ ] The target reconnects automatically and sends a full refresh after a disconnection/restart. - [ ] Device geometry/capabilities are validated before rendering; unsupported devices report a clear reason. - [ ] On a device that advertises compatible partial updates, SideKick sends aligned partial changes and safely falls back to full updates. - [ ] BLE rendering does not require physical display hardware for the existing settings preview. - [ ] A battery-oriented update policy prevents the final-minute per-second flash loop from producing continuous BLE/panel traffic by default. - [ ] Connection failures, transfer failures, and unsupported configurations are observable in logs and the settings UI. ## References - https://github.com/OpenDisplay/Firmware - https://github.com/OpenDisplay/py-opendisplay - https://opendisplay.org/protocol/ble-flow.html - https://github.com/OpenDisplay/Firmware/blob/main/docs/epd-panel-power-session.md - https://github.com/OpenDisplay/Firmware/blob/main/docs/architecture-deep-sleep-power-buttons.md

Comments