Raspberry Pi Pico Firmware for a SDVX or IIDX controller setup. Supports 11 buttons, 10 LEDs, 1 WS2812B strip, and 2 encoders.
  • C 33.6%
  • TypeScript 32.6%
  • Svelte 22.7%
  • Rust 5.2%
  • Shell 3.7%
  • Other 2.2%
Find a file
NullFragment 8ed66d38df
All checks were successful
Build artifacts / Build firmware + desktop bundle (push) Successful in 5m2s
check / Frontend (Svelte + TS) (push) Successful in 32s
check / Firmware host tests (push) Successful in 22s
Rename to sdvx + harden Forgejo CI pipeline
Project Rename (svdx -> sdvx):
- Typo fix across 30 files. The rhythm game is SDVX
  (Sound Voltex), not SVDX.
- Tauri bundle identifier:
  dev.nullfragment.svdx-pico-configurator
  -> dev.nullfragment.sdvx-pico-configurator.
- Rust crate names: svdx-pico-configurator +
  svdx_pico_configurator_lib -> sdvx-pico-configurator +
  sdvx_pico_configurator_lib.
- User config dir: ~/.svdx-pico/ -> ~/.sdvx-pico/
  (capabilities scope + load_config / save_config paths).
- C header guard: SVDX_PICO_TYPES_H -> SDVX_PICO_TYPES_H.
- All docs, plans, and product-name strings
  ("SVDX Pico Configurator" -> "SDVX Pico Configurator").
- Git remote moved to tools/sdvx-pico on Forgejo outside
  this commit.

Forgejo CI (build.yaml):
- Collapsed firmware + desktop + release into a single
  ubuntu-latest job. act v6.4.0 chokes on cross-job
  needs: and on `runs-on: ${{ matrix.os }}` at workflow-
  prepare time, so the multi-job graph + matrix was
  traded for sequential steps in one container.
- Mac / Windows matrix entries kept as commented stubs
  for when workers come online.
- Pinned actions/upload-artifact@v3; v4 uses the new
  GitHub artifact backend Forgejo can't serve
  (GHESNotSupportedError).
- Release publishing now via raw curl against the Forgejo
  (Gitea-compatible) API instead of
  akkuman/gitea-release-action, with hybrid behavior:
  v* tag push -> permanent versioned release; mainline
  branch push -> tear down + recreate a rolling 'latest'
  prerelease pointed at the new SHA.
- Both release paths attach the firmware UF2 plus Linux
  .deb / .AppImage / .rpm bundles.
- jq added to the apt install line for the JSON payload.

Forgejo CI (check.yml):
- Added mainline to push.branches + pull_request.branches
  so merges into the new default branch actually trigger
  CI.

Build Orchestrator (build.sh):
- New populate_release_links mirrors .app / .dmg / .deb /
  .AppImage / .msi bundles from
  configurator/src-tauri/target/release/bundle/ into
  release/ at the repo root via symlinks, giving a stable
  cross-platform path to the latest build.
- Called at the end of build_configurator so every path
  (all / app / clean) refreshes the symlinks.
- clean wipes release/ alongside build/ and
  firmware-tests/build/.
- .gitignore: exclude release/.

Firmware Config:
- src/generated_config.h refreshed with expanded profile
  fields.
- build_uf2/Pico_Game_Controller.uf2 rebuilt to match.
2026-05-20 23:37:36 -07:00
.forgejo/workflows Rename to sdvx + harden Forgejo CI pipeline 2026-05-20 23:37:36 -07:00
build_uf2 Rename to sdvx + harden Forgejo CI pipeline 2026-05-20 23:37:36 -07:00
configurator Rename to sdvx + harden Forgejo CI pipeline 2026-05-20 23:37:36 -07:00
documentation Rename to sdvx + harden Forgejo CI pipeline 2026-05-20 23:37:36 -07:00
firmware-tests Rename to sdvx + harden Forgejo CI pipeline 2026-05-20 23:37:36 -07:00
src Rename to sdvx + harden Forgejo CI pipeline 2026-05-20 23:37:36 -07:00
.gitignore Rename to sdvx + harden Forgejo CI pipeline 2026-05-20 23:37:36 -07:00
build.sh Rename to sdvx + harden Forgejo CI pipeline 2026-05-20 23:37:36 -07:00
CMakeLists.txt Compiled with SDK 2.1.0 2025-02-15 19:58:42 -06:00
demo.gif Added demo gif to readme 2021-09-16 01:41:48 -04:00
LICENSE HID LEDs with reactive fallback, added License, changed switch and led pins 2021-07-08 21:46:26 -04:00
pico_sdk_import.cmake Compiled with SDK 2.1.0 2025-02-15 19:58:42 -06:00
README.md Rename to sdvx + harden Forgejo CI pipeline 2026-05-20 23:37:36 -07:00

Pico-Game-Controller

This branch was developed with SDVX in mind. Capable of handling 7 LEDs, 1 WS2812B RGB strip, and 2 encoders.

Demo of this firmware running on Pocket SDVX Pico v4, purchasable at https://discord.gg/MmuKd73XbY

Pocket SDVX Pico

Quick Build

The fastest path on a fresh machine is the all-in-one script at the repo root:

./build.sh                  # firmware + desktop configurator app (default)
./build.sh firmware         # just the firmware UF2
./build.sh app              # just the desktop app

That script detects your OS, installs cmake / ninja / git / arm-none-eabi-gcc / node / pnpm if any are missing (via brew, apt, pacman, or dnf), then builds whichever stage you asked for. The output .uf2 ends up at build_uf2/Pico_Game_Controller.uf2; the desktop app bundle lands at configurator/src-tauri/target/release/bundle/macos/SDVX Pico Configurator.app (or the platform equivalent under bundle/). First firmware run takes a few minutes for the Pico SDK fetch; subsequent runs are seconds.

Rust toolchain prerequisite for the desktop app. ./build.sh app builds the configurator's Tauri shell, which requires rustup + cargo. The script doesn't auto-install Rust (it's a ~500 MB download you should opt into explicitly):

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env

./build.sh firmware doesn't need Rust.

If you'd rather copy-paste manually:

macOS

brew install cmake ninja git
brew install --cask gcc-arm-embedded   # or download from https://developer.arm.com/downloads if cask is gone
cmake -B build -S . -G Ninja -DPICO_SDK_FETCH_FROM_GIT=on
cmake --build build

Ubuntu / Debian

sudo apt-get install -y cmake ninja-build gcc-arm-none-eabi git
cmake -B build -S . -G Ninja -DPICO_SDK_FETCH_FROM_GIT=on
cmake --build build

Arch

sudo pacman -S --needed cmake ninja arm-none-eabi-gcc arm-none-eabi-newlib arm-none-eabi-binutils git
cmake -B build -S . -G Ninja -DPICO_SDK_FETCH_FROM_GIT=on
cmake --build build

Fedora

sudo dnf install -y cmake ninja-build arm-none-eabi-gcc-cs arm-none-eabi-newlib git
cmake -B build -S . -G Ninja -DPICO_SDK_FETCH_FROM_GIT=on
cmake --build build

Windows

Use the Raspberry Pi Pico VS Code extension — it bundles the SDK + toolchain and Just Works. Install from the marketplace, open this folder, and the build/flash buttons appear in the status bar. Manual setup via the pico-setup-windows installer also works.

Skip the dep install

If your toolchain is already set up and you just want the build:

SKIP_INSTALL=1 ./build.sh firmware

Pin the Pico SDK to a known location

-DPICO_SDK_FETCH_FROM_GIT=on re-fetches the SDK every time you wipe build/. To pin it once:

git clone --depth 1 --branch 2.1.0 https://github.com/raspberrypi/pico-sdk.git ~/pico-sdk
cd ~/pico-sdk && git submodule update --init
# Then build from the repo root:
PICO_SDK_PATH=~/pico-sdk cmake -B build -S . -G Ninja
cmake --build build

Testing

The firmware's pure-logic modules (boot dispatch, NKRO report builder, palette math) have host-runnable unit tests under firmware-tests/. These build with the system C compiler — no ARM cross-compiler or Pico SDK required — and run in milliseconds.

pnpm --dir configurator test:firmware

Or build firmware AND run tests in one shot:

./build.sh firmware --test

Expected output ends with ✓ All firmware tests passed and 32+ tests across three suites (boot_dispatch_suite, keyboard_report_suite, palette_math_suite).

Flashing

Hold the FF (firmware-flash) button on the controller while plugging in via USB-C. The Pico mounts as the RPI-RP2 drive. Drag build_uf2/Pico_Game_Controller.uf2 onto it. The controller auto-reboots into the new firmware as soon as the file write finishes.

Features

  • Gamepad mode — default boot mode
  • NKRO Keyboard & Mouse Mode — hold first button (GPIO 4 / BT-A) to enter kb mode
  • HID LEDs with Reactive LED fallback
  • WS2812B RGB on second core, 2 zones
  • SDVX/IIDX spoof — tested on EAC; see branches release/pocket-sdvx-pico or release/pocket-iidx
  • 1000 Hz polling
  • Reversible encoders with debouncing
  • Switch debouncing
  • Switch and LED pins are staggered for easier wiring
  • Profile-based config: keymaps, LED behavior, and boot triggers all read from src/generated_config.h (see documentation/agentic-context/)

Boot triggers (default config)

Hold one of these while plugging in:

Hold Result
(none) Joystick mode + color-cycle LEDs
BT-A Keyboard + mouse mode
BT-B Turbocharger LED mode
START LEDs off (overrides any other LED mode)

These mappings are configurable per build — see documentation/agentic-context/agent-designs/2026-05-10-configurable-profiles-design.md for the full profile model.

Customizing keybinds & lighting

Tweakable parameters live in src/controller_config.h (compile-time limits and physical layout) and src/generated_config.h (the actual profile data — keymaps, palettes, triggers, overrides). The configurator app under configurator/ provides a GUI for editing the latter; see configurator/README.md.

Walkthrough video covering the pre-refactor (single-keymap) flow: Pocket SDVX Pico v5 Firmware Keybind & Lighting Walkthrough.

Documentation

Full project reference lives under documentation/:

Section Description
Architecture System context, IPC bridge, build & flash flow
Models Profile / ProfileSet schema, Layout, encoder modes
Configuration generated_config.h + ~/.sdvx-pico/config.json schemas
Development Setup, running, testing
Firmware Pico v5 hardware, LED model, encoder dispatch
Agentic context Design docs + implementation plans

Repository layout

src/                      # Firmware source (compiles to .uf2)
configurator/             # Svelte + TS frontend + Tauri (Rust) desktop shell
build.sh                  # Top-level build orchestrator (firmware / app / all)
documentation/            # Project reference docs (start at documentation/README.md)
build_uf2/                # Latest .uf2 lands here after a build
.forgejo/workflows/       # CI: firmware + per-OS desktop bundles

Thanks to