Compare commits

...

12 commits

Author SHA1 Message Date
brentru
b7e6d061aa Add TFT displayType 2025-08-25 11:38:26 -04:00
brentru
fbc883c421 Add Tft constraints 2025-08-25 10:47:38 -04:00
brentru
615ef8c312 Fix for @lorennorman 2025-08-22 13:37:22 -04:00
brentru
465475fd31 Add display.md document 2025-08-21 16:07:51 -04:00
brentru
67c5952e73 Rm width, height. Add name to Response messages 2025-08-20 13:45:21 -04:00
brentru
674f378aba Increase name and message strlens 2025-08-19 13:47:45 -04:00
brentru
000802e92a Rm unused panel configuration 2025-08-18 14:40:24 -04:00
brentru
711bf141eb MagTag is 2.90 not 2.13 2025-08-15 13:33:43 -04:00
brentru
031e9d222d rm extra pins 2025-08-15 12:17:37 -04:00
brentru
c83b680348 Fix import path 2025-08-15 12:06:39 -04:00
brentru
23abc52b66 Add EPD type and panel config 2025-08-15 12:05:10 -04:00
brentru
0933e7cfef Rough draft! 2025-08-14 16:20:11 -04:00
4 changed files with 254 additions and 1 deletions

2
.gitignore vendored
View file

@ -138,3 +138,5 @@ dmypy.json
# Cython debug symbols
cython_debug/
.DS_Store

View file

@ -0,0 +1,83 @@
# display.proto
This file details the WipperSnapper messaging API for interfacing with a display.
## WipperSnapper Components
The following WipperSnapper Components may utilize `display.proto`:
* E-Ink/E-Paper Displays
* TFT Displays
* OLED Displays
* 7-Segment Displays
* Alphanumeric Displays
* LCD Character Displays
## Sequence Diagrams
### Attaching a Display Component to a device running WipperSnapper
```mermaid
sequenceDiagram
autonumber
IO-->>Device: DisplayAddOrReplace
Note over IO, Device: DisplayType field dictates which<br>display we are using (LED, E-Ink, etc)
Device->>ws_display controller: DisplayAddOrReplace
ws_display controller->>ws_display hardware: DisplayAddOrReplace
ws_display hardware->>ws_display driver: Driver Configure Request
ws_display driver->>ws_display hardware: Driver Configure Response
ws_display hardware->>ws_display controller: Hardware Response
ws_display controller-->>Device: DisplayAddedorReplaced
Device-->>IO: DisplayAddedorReplaced
```
### Removing a Display Component from a device running WipperSnapper
```mermaid
sequenceDiagram
autonumber
IO-->>Device: DisplayRemove
Note over IO, Device: name field dictates which<br>display we are removing
Device->>ws_display controller: DisplayRemove
ws_display controller->>ws_display hardware: Delete hardware instance
ws_display hardware->>ws_display driver: Delete driver instance
ws_display driver->>ws_display hardware: Deletion Result
ws_display hardware->>ws_display controller: Deletion Result
ws_display controller-->>Device: DisplayRemoved
Device-->>IO: DisplayRemoved
```
### Writing to a Display from IO
The display message is set by the component's feed value, which is a string. The message is sent to the display driver.
```mermaid
sequenceDiagram
autonumber
IO-->>Device: DisplayWrite
Note over IO, Device: name field dictates which<br>display we are writing to
Device->>ws_display controller: handleDisplayWrite()
ws_display controller->>ws_display hardware: Get display hardware
ws_display hardware->>ws_display driver: Execute writeX()
```

View file

@ -0,0 +1,144 @@
// SPDX-FileCopyrightText: 2025 Brent Rubell for Adafruit Industries
// SPDX-License-Identifier: MIT
// Display API for Adafruit WipperSnapper
syntax = "proto3";
package wippersnapper.display.v1;
import "nanopb/nanopb.proto";
import "wippersnapper/i2c/v1/i2c.proto";
// ============================================================================
// Enums
// ============================================================================
/**
* DisplayType determines the type of display
* and selects which driver should be used.
*/
enum DisplayType {
DISPLAY_TYPE_UNSPECIFIED = 0; /** Unspecified display type. */
DISPLAY_TYPE_OLED = 1; /** OLED display type */
DISPLAY_TYPE_EPD = 2; /** EPD display type */
DISPLAY_TYPE_TFT = 3; /** TFT display type */
}
/**
* EPDMode defines the mode of the EPD display.
* This affects how the display renders images.
*/
enum EPDMode {
EPD_MODE_UNSPECIFIED = 0; /** Unspecified EPD mode */
EPD_MODE_GRAYSCALE4 = 1; /** Grayscale 4 EPD mode */
EPD_MODE_MONO = 2; /** Monochrome EPD mode */
}
// ============================================================================
// Configuration Messages
// ============================================================================
/**
* EpdSpiConfig contains the configuration for SPI-based EPD displays.
* Includes the SPI bus number and pin assignments.
*/
message EpdSpiConfig {
int32 bus = 1; /** The SPI bus to use */
string pin_dc = 2[(nanopb).max_size = 6]; /** Pin for data/command */
string pin_rst = 3[(nanopb).max_size = 6]; /** Pin for reset */
string pin_cs = 4[(nanopb).max_size = 6]; /** Pin for chip select */
string pin_sram_cs = 5[(nanopb).max_size = 6]; /** Pin for SRAM chip select */
string pin_busy = 6[(nanopb).max_size = 6]; /** Pin for busy signal */
}
/**
* EPDConfig contains the configuration for an EPD display.
* It includes the mode, dimensions, and panel type.
*/
message EPDConfig {
EPDMode mode = 1; /** The mode of the EPD display */
}
/**
* EPDWriteOptions contains options for writing to EPD displays.
*/
message EPDWriteOptions {
int32 text_size = 1; /** Scale factor for text (1 = 6x8px, 2 = 12x16px,...) */
}
/**
* TftSpiConfig contains the configuration for SPI TFT displays.
* Includes the SPI bus number and pin assignments.
*/
message TftSpiConfig {
int32 bus = 1; /** The SPI bus to use */
string pin_cs = 2[(nanopb).max_size = 6]; /** Pin for chip select */
string pin_dc = 3[(nanopb).max_size = 6]; /** Pin for data/command */
string pin_mosi = 4[(nanopb).max_size = 6]; /** Pin for MOSI */
string pin_sck = 5[(nanopb).max_size = 6]; /** Pin for SCK */
string pin_rst = 6[(nanopb).max_size = 6]; /** Pin for reset */
string pin_miso = 7[(nanopb).max_size = 6]; /** Pin for MISO */
}
message TftConfig {
int32 width = 1; /** Width of the TFT display in pixels */
int32 height = 2; /** Height of the TFT display in pixels */
int32 rotation = 3; /** Rotation of the display (0-3) */
}
// ============================================================================
// Request Messages
// ============================================================================
/**
* DisplayAddOrReplace adds a new display or replaces an existing one.
*/
message DisplayAddOrReplace {
DisplayType type = 1; /** The type of display */
string name = 2[(nanopb).max_size = 64]; /** Identifier for the display */
oneof interface_type {
EpdSpiConfig spi_epd = 3; /** SPI configuration for EPD */
TftSpiConfig spi_tft = 4; /** SPI configuration for TFT */
}
oneof config {
EPDConfig config_epd = 5; /** Configuration for EPD display */
TftConfig config_tft = 6; /** Configuration for TFT display */
}
}
/**
* DisplayRemove removes an existing display.
*/
message DisplayRemove {
string name = 1[(nanopb).max_size = 64]; /** Identifier for the display. */
}
/**
* DisplayWrite writes content to a display.
*/
message DisplayWrite {
string name = 1[(nanopb).max_size = 64]; /** Identifies the display. */
string message = 2[(nanopb).max_size = 1024]; /** Message to write. */
oneof options {
EPDWriteOptions epd_options = 3; /** Options for writing to EPD displays */
}
}
// ============================================================================
// Response Messages
// ============================================================================
/**
* DisplayAddedorReplaced confirms a display was added or replaced.
*/
message DisplayAddedorReplaced {
string name = 1[(nanopb).max_size = 64]; /** Identifier for the display. */
bool did_add = 2; /** Indicates if a display was added */
}
/**
* DisplayRemoved confirms a display was removed.
*/
message DisplayRemoved {
string name = 1[(nanopb).max_size = 64]; /** Identifies the display. */
bool did_remove = 2; /** Indicates if a display was removed */
}

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2020-2021 Brent Rubell for Adafruit Industries
// SPDX-FileCopyrightText: 2020-2025 Brent Rubell for Adafruit Industries
// SPDX-License-Identifier: MIT
syntax = "proto3";
@ -15,6 +15,7 @@ import "wippersnapper/pwm/v1/pwm.proto";
import "wippersnapper/ds18x20/v1/ds18x20.proto";
import "wippersnapper/pixels/v1/pixels.proto";
import "wippersnapper/uart/v1/uart.proto";
import "wippersnapper/display/v1/display.proto";
/**
* UARTRequest represents a UART command sent to a device.
@ -181,3 +182,26 @@ message PWMResponse {
wippersnapper.pwm.v1.PWMAttachResponse attach_response = 1;
}
}
/**
* DisplayRequest represents a broker's request across the display sub-topic.
*/
message DisplayRequest {
option (nanopb_msgopt).submsg_callback = true;
oneof payload {
wippersnapper.display.v1.DisplayAddOrReplace display_add = 1;
wippersnapper.display.v1.DisplayRemove display_remove = 2;
wippersnapper.display.v1.DisplayWrite display_write = 3;
}
}
/**
* DisplayResponse represents a devices's response across the display sub-topic.
*/
message DisplayResponse {
option (nanopb_msgopt).submsg_callback = true;
oneof payload {
wippersnapper.display.v1.DisplayAddedorReplaced display_added = 1;
wippersnapper.display.v1.DisplayRemoved display_removed = 2;
}
}