Use your Dreamcast controller wirelessly with any Bluetooth device. Pulsar speaks the Dreamcast's Maple Bus protocol natively and presents itself as a standard Xbox One S BLE gamepad — just plug in, pair, and play.
A complete wireless Dreamcast controller, Pulsar on its own, or the parts to build one — at pulsar.alwaysagog.com. Prefer to build it yourself? Start here; everything you need is in this repo.
Where to get Pulsar firmware. The only official sources are this repository's Releases page and the updater at pulsar.alwaysagog.com/update. Firmware ships as
.uf2,.hex, or a signed OTA package — never as a.zip,.exe, or anything you run on a PC. Copies of this repo on other GitHub accounts that offer a "download" have been found carrying malware. Don't run them.
- All Dreamcast inputs: A/B/X/Y, Start, D-pad, analog stick, analog triggers
- Guide/Xbox button via a trigger + Start chord (opens the Steam overlay, Game Bar, etc.)
- Works with any BLE HID host (PC, iOS, Android, Switch, Dreamcast via iBlueControlMod)
- Two switchable identities for broad host compatibility: Xbox (default), or a plain generic BLE HID gamepad (labeled "Dreamcast" — neutral identity, not controller emulation)
- VMU LCD display: profile splash, rotating pulsar with battery indicator, mode splashes
- 60Hz controller polling with continuous BLE reporting
- Pairing persists across power cycles (flash-based bonding)
- Battery powered (~7-8 hrs on 500mAh, ~14-16 hrs on 1000mAh) with sleep/wake support
- 3D-printable VMU-shaped enclosure included
- Standard Dreamcast controller (first-party tested)
Tested:
- Steam Deck (as Xbox gamepad)
- macOS — browser + Steam (as Xbox gamepad)
- Windows — Steam (as Xbox gamepad)
- Linux — xpadneo (as Xbox gamepad)
- Dreamcast (via iBlueControlMod adapter)
Should work (untested):
- iOS, Android (as BLE HID gamepad)
- PlayStation, Nintendo Switch (as generic controller)
One firmware, three boards. They play identically; what differs is what they can show you and how you flash them.
| Board | Status light | Battery | Rumble | Flashing | |
|---|---|---|---|---|---|
| XIAO | Hand-wired DIY build — the one this guide walks through | Onboard RGB | Voltage estimate | — | USB (UF2) |
| Pulsar v1 | Designed carrier with a XIAO mounted on it | 5-LED bar (status + battery) | IP5306 gauge, 4 levels | Yes | Wireless (OTA) |
| DK | nRF52840-DK, bench only | Kit LEDs | — | — | Debug probe |
Pulsar v1 runs the same XIAO module as the DIY build, so the two share their silicon — the carrier adds integrated power management, the LED bar, and a rumble motor around it. Its fabrication files are not published, but the design is described in the bill of materials and all three boards' pin assignments are in pin mapping.
Each board has its own guide, written to be followed start to finish.
| Guide | For | |
|---|---|---|
| 🔧 | Build the XIAO adapter | The hand-wired DIY build. Perfboard, a boost converter, two resistors and two diodes. Soldering required, and it permanently modifies a controller |
| 🧪 | Bench setup on an nRF52840-DK | Development and debugging. No soldering, and no permanent change to a controller if you cut an extension cable instead |
| 📦 | Install an assembled Pulsar v1 | You bought one. Photo-by-photo: open the controller, fit Pulsar, route the cable, close it up |
Once it is together, the user guide covers all three boards, and Pulsar v1 owners have a dedicated owner's manual.
A summary of the XIAO build. The step-by-step version — cable identification, the 5 V diode-OR, pre-power checks and first-boot behaviour — is in docs/build/xiao.md.
- Seeed XIAO nRF52840
- Dreamcast controller
- 5V boost converter (for battery mode)
- 2x 10kΩ resistors
- LiPo battery
- USB cable (for UF2 flashing) or debug probe (for development)
See the full bill of materials for details.
Connect SDCKA and SDCKB from the controller cable to the XIAO with 10kΩ pull-ups to 3.3V. The controller needs 5V power via a diode OR circuit (USB + boost converter). See pin mapping for the complete wiring reference.
Meter your cable before you solder. The colour-to-pin table is the canonical Maple pinout, not a promise about the cable in your hand — third-party and later-revision controllers differ, and getting it wrong puts 5 V on a data line. The build guide walks through checking it with a multimeter, and explains why the diode OR is there and which way round the diodes go.
Pre-built firmware is available on the Releases page.
UF2 (recommended — no debug probe needed):
The XIAO ships with a UF2 bootloader that includes the Nordic SoftDevice. Just double-tap the reset button — the board mounts as a USB drive (XIAO-BOOT) — then copy the .uf2 file:
cp pulsar-dreamcast-ble-xiao.uf2 /Volumes/XIAO-BOOT/The board auto-resets and runs the firmware.
SWD (for development — requires J-Link or nRF52840 DK):
If you need RTT debug logging, flash via SWD instead. The SoftDevice must be flashed separately first — see flash commands for the full workflow.
- Power on the adapter — it starts advertising immediately
- On your host device, scan for "Xbox Wireless Controller"
- Pair and you're done — bonding is saved automatically
Sync button:
- Short press → wake / request reconnect
- Hold 2s → clear bond and start pairing
- Hold 3.5s while holding the controller's Start → firmware update (OTA) mode
- Tap, tap, then hold 3.5s → the same update mode, no controller needed
- Tap once, then hold 3.5s → browser configuration mode (remap your buttons)
- Hold 7s → sleep (
BYEsplash, then powers off) - Triple-press → switch profile (Xbox ⇄ Dreamcast identity)
Guide / Xbox button: pull both triggers and hold Start (~⅓ second) to send the Guide button — opens the Steam overlay / Big Picture, the Xbox Game Bar, etc. Works on both profiles.
The VMU LCD shows the active profile on connect, a rotating pulsar with battery indicator while in use, a home icon when you press the Guide chord, and splashes for pairing (SYNC) and sleeping (BYE).
See the user guide for all screens, profile choice, and troubleshooting.
A 3D-printable VMU-shaped case is included in 3d_files/. See 3d_files/README.md for print tips and attribution.
![]() |
![]() |
![]() |
![]() |
Requires Rust stable with thumbv7em-none-eabihf target:
rustup target add thumbv7em-none-eabihf
cargo install cargo-embedXIAO (must use --release — debug builds break Maple Bus timing):
# Production
cargo embed --release --no-default-features --features board-xiao
# Development (with RTT debug logging)
cargo embed --release --no-default-features --features board-xiao,rttDK (RTT always enabled):
cargo embed --releasePulsar v1 (ships as a signed OTA package; SWD is for bring-up only):
cargo build --release --no-default-features --features board-pulsarv1Each board has a start-to-finish guide under docs/build/.
The maple-protocol crate is pure Rust with no embedded dependencies — tests run on the host:
cd maple-protocol && cargo testThe project is split into two crates:
maple-protocol/— Pure protocol library: controller state parsing, packet construction, Xbox HID report generation. No hardware dependencies, fully host-testable.src/— Firmware: Maple Bus GPIO bit-banging, BLE stack (Nordic SoftDevice S140), board support, button handling, power management.
The GPIO implementation bulk-samples both data lines at ~7.9 MS/s (≈4 samples per 500 ns bit) to capture the 2 Mbps Maple Bus protocol, then decodes in software. This is an nRF52840-specific approach — other chips (e.g., RP2040 with PIO) could implement the same protocol differently. See maple_bus_protocol.md for the full protocol reference.
./scripts/ci.shRuns formatting, the protocol tests, clippy for all three boards, every release build, and
then checks each ELF's timing invariants. ./scripts/check.sh [dk|xiao|pulsarv1] is the ~2 s
inner loop to run after every change; ci.sh is the gate before a commit.
docs/MOC.md indexes everything. The main entries:
| Document | Description |
|---|---|
| Build guides | One per board: XIAO, DK, Pulsar v1 |
| User Guide | Using the adapter, across all three boards |
| Owner's Manual | For an assembled Pulsar v1 |
| Bill of Materials | Parts list for building your own |
| Pin Mapping | Complete wiring reference for all three boards |
| Flash Commands | Flashing and debugging cheat sheet |
| Maple Bus Protocol | Protocol reference and implementation details |
| Input Quality Testing | Measuring latency and packet loss |
| Battery Optimization | Power management strategy |
| Learnings | Implementation lessons learned |
Pre-built firmware is available on the Releases page. Each release includes:
pulsar-dreamcast-ble-xiao.uf2— XIAO firmware, drag-and-drop via UF2 bootloaderpulsar-dreamcast-ble-xiao.hex— XIAO firmware, for flashing via J-Link/SWDpulsar-dreamcast-ble-dk.hex— DK firmware, for flashing via J-Link
3D scan archives are also attached to releases.
Pulsar v1 units update over the air from
pulsar.alwaysagog.com/update; the packages are signed
and the device refuses anything else. There are no other download locations. If a copy of this
repo somewhere else offers a .zip or a Windows program, it isn't ours — see the note at the top.
Contributions are welcome! See CONTRIBUTING.md for build instructions, project structure, and how to submit changes.
This project is licensed under the GNU General Public License v3.0 or later. 3D model files have separate licensing — see 3d_files/README.md.






