BP26 · Hardware walkthrough

An ESP32-C5 badge running Solana OS.

A conference badge that is really a dev board: a 320×240 color screen, a D-pad, eight RGB LEDs, a microSD slot, a 1000 mAh LiPo and three radios on one RISC-V chip. Flash it over USB-C, open it up, write apps for it.

RISC-V · 240 MHz Wi-Fi 6 · 2.4 + 5 GHz ESP-NOW 802.15.4 117 × 78 mm Board by Skyrizz

Specifications

01MCU
ESP32-C5 · RISC-V · 240 MHz
02Board
117 × 78 mm
03Flash
16 MB
04Display
320×240 ILI9341 TFT
05Wi-Fi
Wi-Fi 6 · 2.4 + 5 GHz
06Bluetooth
BLE 5
07Low-power radio
IEEE 802.15.4
08Input
D-pad · SELECT · CANCEL · BOOT
09Light
8× WS2812B RGB
10Storage
microSD
11Battery
3.7 V 1000 mAh LiPo · ADC gauge
12USB
USB-C · CH340C serial

Fig. 01 · Board view

Explore the hardware

Hover or focus a component to highlight it, click to jump to its module. Flip the board to see the module, battery and connectors on the back.

020403
0106050703
Board 117 × 78 mm. Illustration of the final black PCB: outline to scale, parts placed from prototype photos.

01 Module

Compute

A single RISC-V core with two radios bolted on.

The brain is an Espressif ESP32-C5-WROOM module, the shielded can on the back of the board. Inside is an ESP32-C5 (silicon rev 1.2): a single-core 32-bit RISC-V CPU at 240 MHz, a 48 MHz crystal and 16 MB of flash.

There is no PSRAM enabled, so Wi-Fi and the LVGL graphics stack share internal SRAM. Solana OS is built around that budget: one app runs at a time and every app frees its memory when you leave it.

Module
ESP32-C5-WROOM
SoC
ESP32-C5 rev 1.2
CPU
RISC-V, single core, 240 MHz
Crystal
48 MHz
Flash
16 MB
PSRAM
Not enabled
SDK
ESP-IDF v5.5 · FreeRTOS (unicore)
Pin map · Compute
SignalPinNote
Flash (reserved)16–2215 is PSRAM CS1
USB (reserved)13 / 14—
Unused, floating2 / 5 / 26free for hacks

02 Module

Display

320×240 pixels of color TFT over SPI.

An ILI9341 TFT sits in a bracket on the front, driven in landscape at 320×240 over the SPI2 bus. Its flex cable passes through a slot to an FPC connector on the back. The panel is BGR and color-inverted, and the driver rotates it into place.

The UI is rendered with LVGL 9 through esp_lvgl_port. The backlight has its own GPIO, active high, with an external pull-down so it stays dark until firmware turns it on.

Boot splash · color check

Red, green, blue from left to right means the BGR order, inversion and rotation are all right.

Controller
ILI9341
Resolution
320×240, landscape
Bus
SPI2 (shared with microSD)
Color
BGR, inverted
Connector
FPC, on the back
Graphics
LVGL 9
Pin map · Display
SignalPinNote
SPI2 SCKGPIO 9shared with SD
SPI2 MOSIGPIO 10shared with SD
SPI2 MISOGPIO 8shared with SD
LCD CSGPIO 6—
LCD DCGPIO 7—
LCD RSTGPIO 0not independently verified
BacklightGPIO 3active high, ext. pull-down

03 Module

Input

A D-pad, SELECT and CANCEL on the front, BOOT and RST on the back.

The front has a four-way D-pad (UP, DOWN, LEFT, RIGHT) and two action buttons, SELECT and CANCEL. All six sit on a TCA9534 I2C GPIO expander at address 0x20, which pulls an interrupt line low when any of them changes, so the firmware does not have to poll the bus.

On the back, BOOT is wired straight to GPIO 28 with an external pull-up and works as Home in Solana OS. RST resets the chip. All buttons are active low, and Solana OS maps them to logical keys in one place, so apps never read raw button bits.

Signal path

  • 6 front buttons P0–P5 TCA9534
  • TCA9534 I2C 0x20 · SCL 23 / SDA 24 ESP32-C5
  • INT active low GPIO 25
  • BOOT ext. pull-up GPIO 28
Front
UP · DOWN · LEFT · RIGHT · SELECT · CANCEL
Back
BOOT (Home) · RST
Expander
TCA9534 @ I2C 0x20
Logic
Active low
Expander P6/P7
Not connected
Pin map · Input
SignalPinNote
I2C SCLGPIO 23—
I2C SDAGPIO 24—
TCA9534 INTGPIO 25active low
UP · LEFT · RIGHT · DOWNTCA9534 P0–P3active low
SELECT · CANCELTCA9534 P4–P5active low
BOOTGPIO 28ext. pull-up

04 Module

Light

Eight addressable RGB LEDs on a single data pin.

Eight WS2812B addressable LEDs are chained on one GPIO: six across the top edge (silkscreen D3–D8) and two beside the screen on the right edge (D9, D10). They are driven with Espressif's led_strip component.

Full power is blinding and pulls too much current, so the firmware caps brightness at about 24/255. In the reference firmware each held button lights its own LED.

Data chain · GPIO 27

LEDs
8× WS2812B
Layout
6 top (D3–D8) · 2 right (D9, D10)
Data
Single wire, chained
Brightness cap
≈ 24 / 255
Pin map · Light
SignalPinNote
WS2812B DINGPIO 27—

05 Module

Storage

A microSD slot that shares a bus with the screen.

The microSD slot is on the back, on the same SPI2 bus as the display, with its own chip-select on GPIO 4. There is no card-detect pin.

Sharing a bus with a display is harder than it sounds. A freshly powered card starts in SD-native mode and reads MOSI as its command line, whatever the chip-select level. The stock firmware ran about 4 s of LCD tests first, so pixel data reached the card as SD commands. The fix: mount the card before the display starts.

Slot
microSD, SPI mode
Bus
SPI2 (shared with LCD)
Card detect
None
Filesystem
FAT via FatFs
Pin map · Storage
SignalPinNote
SD CSGPIO 4ext. pull-up, reaches DAT3
SCK / MOSI / MISOGPIO 9 / 10 / 8shared with LCD

Boot order

  1. bsp_spi_bus_init()bring up SPI2
  2. bsp_sd_mount()card first, while the bus is quiet
  3. …buttons, LEDs, battery, radios
  4. bsp_display_start()LCD traffic starts last

Four things that broke the SD card

  1. 01

    Bus ordering

    A fresh card listens to MOSI regardless of CS. Solana OS mounts the SD card before it starts the display.

  2. 02

    Lagging error flags

    Some cards report errors on the next command. The driver answers the SDIO probes (CMD52, CMD5) itself instead of sending them.

  3. 03

    Invalid FAT32

    FAT32 volumes with fewer than 65,525 clusters are rejected by FatFs. The firmware detects this and offers an on-device format behind a confirmation.

  4. 04

    Cards that ignore CS

    Some no-name cards keep executing bus traffic while deselected. The firmware detects them and refuses to use them rather than risk random reads or erases.

Takeaway: use a name-brand microSD card. The first three are fixed in firmware; the fourth is the card.

06 Module

Connectivity

Dual-band Wi-Fi 6, BLE 5 and 802.15.4 on one chip, plus USB-C.

The ESP32-C5 has dual-band Wi-Fi 6 (2.4 and 5 GHz), Bluetooth LE 5 and an IEEE 802.15.4 radio. Solana OS uses Wi-Fi and ESP-NOW and leaves Bluetooth out of the firmware to save RAM.

For wired access there is a USB-C port on the back. UART0 goes through a CH340C USB-serial bridge, which carries flashing and a serial console at 115200 baud with commands like help, info, sd, ls, cat and rgb.

Wi-Fi
Wi-Fi 6, 2.4 + 5 GHz
Bluetooth
BLE 5 (not used by Solana OS)
Low-power radio
IEEE 802.15.4
USB
USB-C
USB-serial
CH340C
Console
115200 baud
Pin map · Connectivity
SignalPinNote
UART0 TXGPIO 11to CH340C
UART0 RXGPIO 12from CH340C

07 Module

Power

A 1000 mAh LiPo, an OFF/ON switch and an ADC fuel gauge.

A 3.7 V 1000 mAh LiPo pouch (523450) covers the lower half of the back and plugs into a JST connector. An OFF/ON slide switch on the left edge cuts power.

There is no dedicated fuel-gauge chip. The battery voltage goes through a 1:1 resistor divider into ADC1 on GPIO 1, and firmware doubles the reading. Solana OS shows the result as a percentage in the status bar, and the Hardware Debug app shows millivolts too.

Battery sense

Vbat = 2 × VADC1 · GPIO 1

Battery
3.7 V 1000 mAh LiPo
Cell
523450 pouch
Connector
JST
Switch
OFF / ON slide
Fuel gauge
ADC, no gauge IC
Divider
1:1 (reading ×2)
Pin map · Power
SignalPinNote
Battery senseGPIO 1ADC1, 1:1 divider

Firmware · ESP-IDF v5.5 · LVGL 9

Solana OS

The badge firmware. It builds and runs today: a launcher, a status bar, one input layer and a growing set of apps, set in ABC Diatype on the device. It runs one app at a time and hands it the screen.

Try it in the emulator
Solana OS launcher with six app tiles

Screenshot from a real badge · 320×240

Launcher

The home screen is an app browser: a grid of every registered app that pages as the catalog grows. The focused tile lights up in the Solana gradient.

  • Status bar: Solana logomark, app title, Wi-Fi, battery %
  • Move with the D-pad, open with SELECT
  • BOOT always brings you back here
  • One app runs at a time and frees its memory on exit

Controls

The default mapping. Apps read logical keys, so the mapping lives in one header and can change without touching apps.

ButtonDoesWhere
UPMove upFront · D-pad
DOWNMove downFront · D-pad
LEFTMove leftFront · D-pad
RIGHTMove rightFront · D-pad
SELECTOpen / confirmFront
CANCELCancel / go backFront
BOOTHomeBack

More apps coming

Wi-Fi, My Badge, ESP-NOW, HW Debug, Settings and About are the first six. Adding an app is a new directory under apps/, one entry in sources.cmake and one line in the registry; the badge and the emulator both pick it up. The descriptor below is the real one from the firmware.

App model
// firmware/main/core/os.h - one descriptor per app,// listed in firmware/main/apps/registry.ctypedef struct {    const char *id;                 // console: "open wifi"    const char *name;               // launcher + status bar title    const char *symbol;             // LV_SYMBOL_* icon, or NULL...    const lv_image_dsc_t *icon;     // ...to use an image    uint32_t accent;    void (*on_enter)(lv_obj_t *root);   // build UI in the OS-owned root    void (*on_exit)(void);          // stop tasks/radios/timers, free memory    bool (*on_key)(os_key_t key, bool repeat);  // false = not handled    void (*on_tick)(void);          // every 100 ms, LVGL locked} os_app_t;

Web Serial · USB-C

Flash your badge

Put Solana OS 0.4.4 on your badge straight from this page: plug it in over USB-C, pick its port, flash. Nothing to install. Developers can build it from source instead.

Erase options, release and re-link, and an offline download for esptool are on the Stock firmware page.

Loading the flasher…