Hardware Platform Support
SeedSigner supports multiple hardware platforms via runtime profile detection and per-platform IO mappings.
For a consolidated per-profile mapping table and GPIO40 header reference, see docs/io_config.md.
Where platform support is defined
src/seedsigner/hardware/io_config.json- Source of truth for supported models, detection regex patterns, and IO pin maps.
src/seedsigner/hardware/io_config.py- Loads platform definitions and resolves runtime profile to hardware profile.
src/seedsigner/models/settings.py- Detects runtime profile from
/proc/device-tree/model. - Applies platform defaults for hardware profile, display config, and camera rotation.
- Detects runtime profile from
How detection works
- Device model string is read from
/proc/device-tree/model. - Regex patterns in
io_config.jsonare matched to select aruntime_profile. - Runtime profile is mapped to a hardware profile (
shortname, e.g.RPI_40). - Hardware profile pin mappings are used by hardware modules (display, buttons, camera).
Supported platform profiles
Current profiles in io_config.json:
RPI_40(Raspberry Pi 40-pin variants, includes Zero/Zero W/Zero 2 W and newer Pis)RPI_26(legacy Raspberry Pi 26-pin variants)FOX_22(Luckfox Pico 22-pin)FOX_40(Luckfox Pico 40-pin)FOX_PI(Luckfox Pico Pi)LC_LAFRITE(Libre Computer La Frite AML-S805X-AC, USB camera)
Supported displays
SeedSigner supports several SPI display modules. The active display driver is selected via Settings → Hardware → Display type (or via a SettingsQR).
| Display | Config value | Resolution | Driver | Notes |
|---|---|---|---|---|
| Waveshare 1.3” LCD HAT (ST7789) | st7789_240x240 | 240×240 | ST7789.py | Default; original SeedSigner display |
| ST7789 320×240 (e.g. 2.0” IPS) | st7789_320x240 | 320×240 | st7789_mpy.py | Natively portrait; 90° rotation applied |
| Waveshare 1.44” LCD HAT (ST7735S) | st7735_128x128 | 128×128 | ST7735.py | UI renders at 240×240 and downscales |
| ILI9341 320×240 | ili9341_320x240 | 320×240 | ili9341.py | Beta support |
The Waveshare 1.3” and 1.44” LCD HATs share the same GPIO40 header pinout and use the same RPI_40 hardware profile — only the display driver setting differs. See docs/io_config.md for wiring details.
Display switching shortcut (very-long-press)
While on the home screen, holding the joystick in one direction for 5 seconds or more will switch the display driver without navigating to Settings. This is useful when the current display setting doesn’t match the physical hardware (e.g. after swapping HATs) and the screen is unreadable.
| Joystick direction | Switches to |
|---|---|
| Up (hold 5 s) | ST7789 240×240 |
| Right (hold 5 s) | ST7789 320×240 |
| Down (hold 5 s) | ST7735 128×128 |
The setting is persisted if Persistent Settings is enabled. After switching, the home screen re-renders automatically with the new display dimensions.
Button GPIO mapping format
Button mappings live under each model’s buttons object.
Accepted entry formats:
[gpiochip_path, line]- Example:
["/dev/gpiochip1", 25]
- Example:
[gpiochip_path, line, bias]- Example:
["/dev/gpiochip0", 6, "pull_up"]
- Example:
[line](platforms using global line numbering with periphery)- Example:
[58]
- Example:
[line, bias]- Example:
[6, "pull_up"]
- Example:
bias is optional. When present as the last string element (e.g. [chip, line, "pull_up"] or [line, "pull_up"]), it is passed to periphery.GPIO(..., bias=<value>). When absent, input GPIO is opened without an explicit bias.
For Raspberry Pi profiles (RPI_40, RPI_26), button entries are configured with inline "pull_up" bias to match active-low button reads.
IO mapping summary by profile
This is a quick reference summary of the mappings currently defined in src/seedsigner/hardware/io_config.json.
RPI_40
- Display:
dc:["/dev/gpiochip0", 25]rst:["/dev/gpiochip0", 27]bl:["/dev/gpiochip0", 24]- SPI:
bus 0,device 0
- Buttons (all with
"pull_up"):KEY_UP:["/dev/gpiochip0", 6, "pull_up"]KEY_DOWN:["/dev/gpiochip0", 19, "pull_up"]KEY_LEFT:["/dev/gpiochip0", 5, "pull_up"]KEY_RIGHT:["/dev/gpiochip0", 26, "pull_up"]KEY_PRESS:["/dev/gpiochip0", 13, "pull_up"]KEY1:["/dev/gpiochip0", 21, "pull_up"]KEY2:["/dev/gpiochip0", 20, "pull_up"]KEY3:["/dev/gpiochip0", 16, "pull_up"]
- Camera:
- Resolution:
480x480 - Framerate:
4
- Resolution:
RPI_26
- Display:
dc:["/dev/gpiochip0", 25]rst:["/dev/gpiochip0", 27]bl:["/dev/gpiochip0", 24]- SPI:
bus 0,device 0
- Buttons (all with
"pull_up"):KEY_UP:["/dev/gpiochip0", 3, "pull_up"]KEY_DOWN:["/dev/gpiochip0", 17, "pull_up"]KEY_LEFT:["/dev/gpiochip0", 2, "pull_up"]KEY_RIGHT:["/dev/gpiochip0", 22, "pull_up"]KEY_PRESS:["/dev/gpiochip0", 4, "pull_up"]KEY1:["/dev/gpiochip0", 23, "pull_up"]KEY2:["/dev/gpiochip0", 18, "pull_up"]KEY3:["/dev/gpiochip0", 14, "pull_up"]
- Camera:
- Resolution:
480x480 - Framerate:
4
- Resolution:
FOX_22
- Display:
dc:["/dev/gpiochip1", 20]rst:["/dev/gpiochip1", 19]bl:"disabled"- SPI:
bus 0,device 0
- Buttons (all with
"pull_up"):KEY_UP:["/dev/gpiochip1", 25, "pull_up"]KEY_DOWN:["/dev/gpiochip1", 23, "pull_up"]KEY_LEFT:["/dev/gpiochip1", 24, "pull_up"]KEY_RIGHT:["/dev/gpiochip0", 4, "pull_up"]KEY_PRESS:["/dev/gpiochip1", 22, "pull_up"]KEY1:["/dev/gpiochip4", 16, "pull_up"]KEY2:["/dev/gpiochip4", 17, "pull_up"]KEY3:["/dev/gpiochip1", 21, "pull_up"]
- Camera:
- Device:
/dev/video12 - Pixel format:
GREY - Framerate:
6
- Device:
FOX_40
- Display:
dc:["/dev/gpiochip2", 8]rst:["/dev/gpiochip1", 24]bl:["/dev/gpiochip1", 25]- SPI:
bus 0,device 0
- Buttons (all with
"pull_up"):KEY_UP:["/dev/gpiochip2", 9, "pull_up"]KEY_DOWN:["/dev/gpiochip1", 26, "pull_up"]KEY_LEFT:["/dev/gpiochip1", 19, "pull_up"]KEY_RIGHT:["/dev/gpiochip1", 20, "pull_up"]KEY_PRESS:["/dev/gpiochip1", 27, "pull_up"]KEY1:["/dev/gpiochip1", 23, "pull_up"]KEY2:["/dev/gpiochip1", 22, "pull_up"]KEY3:["/dev/gpiochip1", 21, "pull_up"]
- Camera:
- Device:
/dev/video12 - Pixel format:
GREY - Framerate:
6
- Device:
FOX_PI
- Display:
dc:["/dev/gpiochip1", 27]rst:["/dev/gpiochip1", 24]bl:["/dev/gpiochip2", 6]- SPI:
bus 0,device 0
- Buttons (all with
"pull_up"):KEY_UP:["/dev/gpiochip3", 25, "pull_up"]KEY_DOWN:["/dev/gpiochip0", 1, "pull_up"]KEY_LEFT:["/dev/gpiochip3", 26, "pull_up"]KEY_RIGHT:["/dev/gpiochip0", 0, "pull_up"]KEY_PRESS:["/dev/gpiochip1", 20, "pull_up"]KEY1:["/dev/gpiochip4", 17, "pull_up"]KEY2:["/dev/gpiochip3", 27, "pull_up"]KEY3:["/dev/gpiochip1", 23, "pull_up"]
- Camera:
- Device:
/dev/video12 - Pixel format:
GREY - Framerate:
6
- Device:
LC_LAFRITE
- Display (explicit gpiochip + line selectors; 7J1 header, Waveshare-compatible physical pin positions):
dc:["/dev/gpiochip1", 79](pin 22, sysfs 480, GPIOX_0)rst:["/dev/gpiochip1", 20](pin 13, sysfs 421, GPIOH_4)bl:["/dev/gpiochip1", 25](pin 18, sysfs 426, GPIOH_9)- SPI:
bus 0,device 0
- Buttons (all with
"pull_up"; explicit gpiochip + line mappings):KEY_UP:["/dev/gpiochip0", 2, "pull_up"](pin 31, sysfs 503, GPIOAO_2)KEY_DOWN:["/dev/gpiochip1", 86, "pull_up"](pin 35, sysfs 487, GPIOX_7)KEY_LEFT:["/dev/gpiochip1", 76, "pull_up"](pin 29, sysfs 477, GPIODV_27)KEY_RIGHT:["/dev/gpiochip1", 84, "pull_up"](pin 37, sysfs 485, GPIOX_5)KEY_PRESS:["/dev/gpiochip1", 85, "pull_up"](pin 33, sysfs 486, GPIOX_6)KEY1:["/dev/gpiochip1", 83, "pull_up"](pin 40, sysfs 484, GPIOX_4)KEY2:["/dev/gpiochip1", 82, "pull_up"](pin 38, sysfs 483, GPIOX_3)KEY3:["/dev/gpiochip1", 81, "pull_up"](pin 36, sysfs 482, GPIOX_2)
- Camera (USB):
- Device:
/dev/video1 - Resolution:
1280x720 - Pixel format:
YUYV - Framerate:
4
- Device: