Selected work

Aetheris-ESP32-C6

Aetheris Rust firmware for ESP32-C6

  • Rust
Featured

Aetheris

Rust ESP32-C6 Embassy Wokwi SSD1306 GitHub

Aetheris is a Rust phone-style firmware for the ESP32-C6. It uses the Espressif ROM and bootloader underneath; it is an embedded device environment, not a PC-class operating system.

Technology stack

┌──────────────────────────────────────────────────────────────┐
│ Aetheris: login · home · app launcher · settings · piano      │
│ 24 compact apps · T9 text entry · wallpapers · sound cues       │
├──────────────────────────────────────────────────────────────┤
│ Rust 2024 · no_std · Embassy async runtime · esp-hal 1.2        │
├──────────────────────────────────────────────────────────────┤
│ SSD1306 I²C · embedded-graphics · GPIO matrix · Wi-Fi station   │
│ NEC IR decode · software tone generation · OTA-ready partitions │
├──────────────────────────────────────────────────────────────┤
│ ESP32-C6 · RISC-V · 2.4 GHz Wi-Fi · GPIO · I²C · internal flash │
└──────────────────────────────────────────────────────────────┘
                ┌──────────── OLED 1 @ 0x3C ────────────┐
ESP32-C6 I²C ───┤                                      ├─ navigation UI
 GPIO6 SDA      └──────────── OLED 2 @ 0x3D ────────────┘  status dashboard
 GPIO7 SCL              (if address is selectable)

 GPIO0..3 ── keypad rows R1..R4     GPIO10,11,18,19 ── columns C1..C4
 GPIO4     ── IR receiver OUT       GPIO22 ── LED + series resistor
 GPIO23    ── passive buzzer IO     GND shared by every module

Firmware behavior

Boot, login and home

  • The OLED boot sequence shows a falling digital-rain animation, Aetheris branding, “Powered by Seleste Technologies”, and a two-note boot cue.
  • The login accepts username and password through phone-style multi-tap input. Defaults are username aetheris and password 1234.
  • On the login screen, A switches the username/password field, B or * deletes a character, C clears the selected field, and D toggles uppercase. Number keys use multi-tap groups (2=abc, 3=def, …); 0 is space. Press # to submit. Repeated presses of the same key within 900 ms cycle its letters. Each key's digit is the final character in its group (for example, cycle 2 through a, b, c, then 2).
  • The Home screen opens Apps (A), Settings (B), Piano (D), or the Apps list (*); # opens Dice. The 128×64 navigation screen uses large 6×10 labels, a 10×20 home title, vector drawn app icons, and a separate secondary OLED dashboard when a second address is available. The Settings icon is a drawn gear, and the apps menu contains 28 entries.
  • Username, password, Wi-Fi credentials, notes and wallpaper choice currently live in RAM. The Security app can change login credentials for the current boot; credentials are not stored across reboot.

Applications

AppBehavior
Piano24 chromatic frequencies, C4–B5 (C♯/D♭ etc. share equal-tempered pitches); number keys plus A/B select notes; C/D choose octave; # enables a major triad arpeggio
TerminalUSB serial status/help, Wi-Fi scan and reboot commands
MatrixAnimated digital-rain display
ClockUptime clock
TimerAdjustable countdown with completion melody
StopwatchStart/pause/reset stopwatch
NotesT9 text editor, held in RAM
Calculator32-bit integer add/subtract/multiply/divide
IR RemoteNEC frame monitor and last-code display
BuzzerTest tones
Wi-FiScan, select an access point, enter its password and associate
System InfoESP32-C6 identity and Wi-Fi link status
SettingsWallpaper, Wi-Fi setup and reboot
WallpaperSwitch the primary/secondary display theme
CounterA increments, B decrements, C resets
Coin FlipAnimated coin toss with short tick sequence and result tone
Wi-Fi ScanScan and choose nearby access points
Sound TestPlay tones from the keypad
Key TestDisplay/log the last key pressed
Display TestChange display theme and check both OLEDs
SecurityEdit username/password for the current boot
UpdateReports OTA readiness; network download/verification is not implemented
RebootSoftware reset
PowerOLED-off mode; any keypad key wakes the UI
DiceAnimated, audible D4/D6/D8/D10/D12/D20 roll; A changes die, # rolls
MetronomeAudible 40–240 BPM beat; A/B adjust tempo, # starts/stops
SnakeKeypad controlled grid game; A/B/C/D steer and # starts/pauses
Reaction TestWait for the GO cue and press # to measure reaction time

The passive buzzer is driven with a full 3.3 V GPIO swing and a 50% tone duty cycle. Firmware cannot make a directly connected passive buzzer louder than that; use a transistor driver or audio amplifier for more volume. It cannot produce speech or recorded voice. Major chords are played as an arpeggio because one buzzer is a single sound source.

Wi-Fi and IR

Wi-Fi setup performs an access point scan, shows the discovered SSIDs, lets you select one, then accepts a T9 password. A successful station association lights the green LED and shows WIFI: ON ~)) on the home screen. The Wi-Fi link state is not a guarantee of internet access; DHCP/IP networking and credential persistence are not configured. Credentials are held only in RAM.

The IR receiver is sampled as a demodulating receiver and standard 32-bit NEC frames are decoded/logged. Each valid NEC frame toggles display power, so a remote button can put the OLEDs to sleep or wake them. Other IR protocols are not decoded.

OTA

The 16 MB flash layout reserves a factory image, two 2 MB OTA slots, OTA metadata, NVS and a storage partition. The application currently does not download or verify a firmware image or switch slots. A safe OTA client still needs network transport, signed-image verification, rollback confirmation, and device testing.

Wiring

Power logic from 3.3 V and share ground. Confirm pin labels and availability on your exact carrier board/module before wiring. The plan avoids GPIO5, 8, 9 and 15 (boot/strapping-sensitive pins), GPIO12/13 (USB Serial/JTAG), and GPIO16/17 (UART0 console on common C6 boards). GPIO4 is assigned to the IR receiver as requested; some older ESP32-C6 documentation also identifies GPIO4 as a strap pin, so use an IR receiver whose OUT rests high and verify normal reset/boot with the module connected.

PartPin/signalESP32-C6 connection
Both OLEDsSDAGPIO6
Both OLEDsSCK/SCLGPIO7
Both OLEDsVDD3V3
Both OLEDsGNDGND
Matrix keypadR1, R2, R3, R4GPIO0, GPIO1, GPIO2, GPIO3
Matrix keypadC1, C2, C3, C4GPIO10, GPIO11, GPIO18, GPIO19
IR sensorOUTGPIO4
IR sensorVCC, GND3V3, GND
Green LEDGPIO side through 220–1kΩ resistorGPIO22
Green LEDCathodeGND
Passive buzzerIOGPIO23; add a transistor if current requires it
Passive buzzerGND, VSSGND and module-rated supply per its label

Use this standard 4×4 scan layout:

R1: 1  2  3  A
R2: 4  5  6  B
R3: 7  8  9  C
R4: *  0  #  D
    C1 C2 C3 C4

Your listed key labels contain 15 keys (0..8, A..D, *, #), while the description says the membrane has 8 keys. The firmware assumes the common eight-wire 4×4 matrix, with one unused position. Verify the ribbon's row/column mapping with a continuity meter; edit KEYMAP and the GPIO assignments if the membrane is laid out differently.

OLED placement

OLED 1 at 0x3C is the primary navigation display. If OLED 2 can be strapped to 0x3D, it shows a separate Aetheris/Wi-Fi/current-app dashboard and uses the alternate wallpaper. Many modules are fixed at 0x3C; two such screens on the same wires mirror one another and cannot show different images. Independent control requires one 0x3D display or a TCA9548A I²C multiplexer. The yellow/ blue panel's color split is fixed by the screen hardware. This driver expects SSD1306-compatible modules; SH1106 panels need a matching driver.

Flash layout

partitions.csv defines a 16 MB layout and partitions.bin is the generated ESP-IDF binary table. Local espflash.toml selects this table and the 16 MB flash size. Each application slot is 2 MB; the current release image fits. The first flash writes this partition table, so it replaces any existing layout.

Build and flash

cargo build --release
cargo run --release

.cargo/config.toml targets riscv32imac-unknown-none-elf; cargo run uses espflash to flash and open the serial monitor. Connect USB and use the board's BOOT/RESET download-mode procedure if required. This firmware has been release-built and checked against the partition-table app slot, but it has not been run on the physical board; confirm the module variant, OLED controller and address, keypad wiring, and buzzer current before relying on it.

Source map

src/bin/main.rs   Hardware initialization, UI loop, Wi-Fi, keypad, IR, buzzer
src/lib.rs        Aetheris identity, app catalog, T9/piano tables
partitions.csv    Factory + OTA0/OTA1 + data partitions for 16 MB flash
partitions.bin    espflash-ready ESP-IDF partition table
espflash.toml     Selects the partition table and flash size
CODEX.md          Generated ESP32-C6 project rules

Visit project ↗

← All projects