Skip to content

Latest commit

 

History

178 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Schnell BLE Keypad

⌨️ Firmware for Schnell Keypad — a wireless macro keypad built on the Espressif ESP32-S3-WROOM-1, by DriftKingTW.

It works as both a USB HID keyboard and a Bluetooth LE keyboard, with on-device layout switching, macros, a rotary encoder, an OLED display, and a Wi-Fi configuration page.

Features

  • Dual output — switch on the fly between USB HID and BLE HID.
  • 5 × 7 key matrix with multiple, switchable layouts.
  • Macros — key-stroke combos, string output, or string + Enter.
  • Tap-Toggle layers — momentary layer switch, double-tap to lock.
  • Rotary encoders — onboard encoder plus an optional I²C extension board (PCF8574: 3 keys + encoder).
  • Bi-directional switch for quick layout cycling.
  • OLED status display (SSD1306 128×32) — battery, connection, layout, key feedback.
  • WS2812 status LED and battery monitoring with low-battery alert.
  • Power management — auto screen sleep, deep sleep with key-press wake, "caffeinated" (stay-awake) and output-lock modes.
  • Configuration — Wi-Fi web UI, Improv serial provisioning, or direct serial keyconfig.json upload.

Hardware

Part Detail
MCU ESP32-S3-WROOM-1 (N4R2 — 4 MB flash, 2 MB PSRAM)
Display SSD1306 128×32 OLED (I²C)
LED 1× WS2812
Input 5×7 matrix, onboard rotary encoder, bi-directional switch, 3 config buttons
Extension (optional) PCF8574 rotary-encoder board @ 0x38

The board definition lives in boards/esp32-s3-wroom-1-n4r2.json so the project builds without any local PlatformIO customization.

Project structure

The firmware is organized into focused modules under src/:

Module Responsibility
main.cpp setup()/loop(), FreeRTOS tasks, key/power/config logic
usbhid / blehid USB / BLE HID transport wrappers (each isolates one HID library)
keyboard_output KeyboardOutput interface over USB/BLE
config_store parses & caches keyconfig.json once
display_state mutex-guarded OLED state
web_server HTTP configuration server + Improv provisioning
helper.hpp small SPIFFS/format helpers

⚠️ Note for contributors: USBHIDKeyboard.h (TinyUSB) and BleKeyboard.h (NimBLE) define conflicting macros and must not be included in the same translation unit — that is why each is wrapped in its own module. Module .cpp files should not include main.hpp or helper.hpp; depend on main via extern declarations instead.

Building

This is a PlatformIO project.

pio run                 # build firmware
pio run -t upload       # build + flash over USB
pio run -t uploadfs     # build + flash the SPIFFS filesystem (web UI + config)
pio device monitor      # serial monitor

Environment: esp32-s3-wroom-1-n4r2 (see platformio.ini).

Flashing a release

Each release ships prebuilt binaries. Flash offsets for the N4R2 (no-OTA) layout:

File Offset Contents
firmware-merged.bin 0x0 bootloader + partitions + app (program only)
spiffs.bin 0x210000 filesystem (web UI + default config)
# Update the program only (keeps existing settings):
esptool.py --chip esp32s3 write_flash 0x0 firmware-merged.bin

# Fresh device (program + filesystem):
esptool.py --chip esp32s3 write_flash 0x0 firmware-merged.bin 0x210000 spiffs.bin

Re-flashing spiffs.bin overwrites the on-device configuration with the packaged defaults. To change only the program, flash firmware-merged.bin alone. Helper scripts are also provided in tools/.

Configuration

  • Web UI — long-press the boot-mode config button to enter Wi-Fi mode, then open http://schnell.local (or the IP shown on the OLED). Keymaps, macros, layouts and network settings can be edited live. The companion editor is the Schnell Keypad Configuration Tool.
  • Improv — provision Wi-Fi credentials over serial.
  • Serial — paste a keyconfig.json into the serial monitor to update the keymap directly.

Releases & CI

GitHub Actions handles builds and releases automatically:

  • CI (.github/workflows/ci.yml) — compiles on every push / PR to master.
  • Release (.github/workflows/release.yml) — pushing a v* tag builds the firmware, SPIFFS image and merged binary, publishes a GitHub Release with the artifacts attached, and then notifies the web configuration tool (see below).

The in-firmware version string is injected from the git tag at build time (scripts/version.py), so it always matches the release.

Use an annotated tag — its message is reused as the Discord announcement text (see below), so write a short, user-facing summary:

git tag -a v1.2.0 -m "Add macro export; fix occasional Bluetooth disconnects."
git push origin v1.2.0   # use -beta.N / -rc.N for pre-releases

Auto-publish to the web installer

After the release is created, release.yml sends a repository_dispatch to the Schnell Keypad Configuration Tool, which downloads the new firmware-merged.bin + spiffs.bin and publishes them to its in-browser firmware installer — no manual upload needed.

  • A stable tag (e.g. v1.2.0) updates the installer's stable channel and is archived so it stays selectable as an older version.
  • A pre-release tag (containing beta/rc, e.g. v1.2.0-beta.1) updates the beta channel, which only ever keeps the latest build.

This requires a WEB_TOOL_DISPATCH_TOKEN repository secret — a Personal Access Token with Contents: read and write on the configuration-tool repo (the default GITHUB_TOKEN cannot trigger workflows across repositories).

Discord announcement

release.yml also posts an announcement to a Discord channel: the version and channel (Stable/Beta), a link to the in-browser installer (pre-selected to the matching channel), and a link to the GitHub release.

  • The embed description uses the annotated tag message, so keep it short and user-facing. A lightweight tag (no message) falls back to a generic line.
  • Set a DISCORD_WEBHOOK_URL repository secret to a channel webhook. The step is skipped if it is unset and never fails the release if Discord is down.

License

Licensed under the GNU General Public License — see LICENCE.

About

Firmware for Schnell BLE keypad based on custom ESP32S3 board

Resources

Stars

8 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages