SN2040 is a Raspberry Pi Pico firmware (based off GP2040-CE) which acts as a SNES controller to USB adapter, plugging into a PC (or some game consoles). This way you don't have to modify or replace your SNES controller's PCB with a USB-compatible one, to use your controller with a PC.
This is one of the cheapest ways to use a real SNES controller on a PC, requiring only a $4 Raspberry Pi Pico, cutting your controller's original cable (or buying a female SNES controller connector and soldering it to a PCB, not supplied), a Micro-USB cable, and soldering equipment (and hot-gluing the Pico into whatever plastic case you have lying around, I used a Magic Joy Box for extra irony).
In comparison, the Raphnet adapter costs over $20. The Arduino-based DaemonBite and Triple Controller cost $10-20 to purchase; if you build them yourself, they require Arduinos which officially cost over $20, though you can get compatible clones for under $4 on AliExpress, actually cheaper than a Pi Pico! (Triple Controller parts list) The Arduino adapters have slightly less latency in their USB stack (under 1ms of difference), but their current firmware does not support XInput over USB.
First install the Pico C/C++ SDK (instructions) and build this project (producing a GP2040-CE_0.6.2_Pico.uf2
file). Then plug the Pi Pico into your system and drag the .uf2
file into the Pico's virtual flash drive. Now disconnect the Pico from your PC and proceed to hardware assembly:
Take a SNES controller cable with plug cut off. (See the connector's pinout, source.)
- Solder its 5V wire (white) to Pico pin 36 (3.3V output).
- Solder its clock, latch, and data pins (yellow, orange, red) to Pico pins 9-11 (GPIO 6-8).
- Solder its ground wire (brown) to any Pico ground pin (see pinout diagram).
These instructions run the SNES controller at 3.3 volts rather than 5 volts, which seems to work largely fine (previously documented at Reddit, deleted comments).
If you instead solder the SNES 5V wire to the Pico's 5V pins (40 or 39), the controller will seem to work, but the controller will be driving 5V through its data output line, to the Pico's Pin 11 (GPIO 8), which may fry the Pico over time. I've run it this way by mistake for a day or so before switching to 3.3 volts, and the Pico still seems to be working fine... for now...
If you have ordered SNES controller ports, you could design and order a custom PCB with a controller port leading to a Pi Pico or RP2040 chip's GPIO pins, allowing for easy controller unplugging. I did not attempt this.
If you have multiple official SNES controller cables, you can swap the controller between a regular cable and one with a Pico hard-wired to the other side, by disassembling the controller and disconnecting the cable from the PCB inside. This is less convenient than unplugging the SNES controller normally though.
Pressing Select+Start+D-Pad
will map the hardware D-Pad to the left or right emulated analog stick, instead of D-Pad. Press Select+Start+Down
to reset the D-Pad to normal functionality.
For a full list of preprogrammed button shortcuts, see https://gp2040-ce.info/#/usage and https://gp2040-ce.info/#/gp2040-shortcuts. Be sure to pick "Nintendo Switch" button labels for correct face button names.
Original README:
GP2040-CE is a gamepad firmware for the Raspberry Pi Pico and other boards based on the RP2040 microcontroller, and provides high performance with a rich feature set across multiple platforms. GP2040-CE is compatible with PC, MiSTer, Android, Raspberry Pi, Nintendo Switch, PS3 and PS4 (legacy controller support).
Full documentation can be found at https://gp2040-ce.info.
- Selectable input modes - XInput, DirectInput, and Nintendo Switch
- Overclocked polling rate for less than 1 ms of input latency in all modes
- Multiple SOCD cleaning modes - Neutral, Up Priority (a.k.a. Stickless), and Second Input Priority
- Left and Right stick emulation via D-pad inputs as well as dedicated toggle switches
- Dual direction via D-pad + LS/RS
- Reverse input via button
- Turbo and Turbo LED with selectable speed
- Per-button RGB LED support
- PWM Player indicator LED support (XInput only)
- Multiple profile support
- Support for 128x64 monochrome I2C displays - SSD1306, SH1106, and SH1107 compatible
- Custom startup splash screen and easy image upload via web configuration
- Support for passive buzzer speaker (3v or 5v)
- Built-in, embedded web configuration - no download required!
Visit the GP2040-CE Usage page for more details.
Input latency is tested using the methodology outlined at WydD's inputlag.science website, using the default 1000 Hz (1 ms) polling rate in the firmware.
Version | Mode | Poll Rate | Min | Max | Avg | Stdev | % on time | %1f skip | %2f skip |
---|---|---|---|---|---|---|---|---|---|
v0.3.1 | All | 1 ms | 0.56 ms | 1.32 ms | 0.85 ms | 0.24 ms | 95.95% | 4.05% | 0% |
Full results can be found in the GP2040-CE Firmware Latency Test Results Google Sheet.
Prebuilt uf2
files are available in the Releases section.
The default pinout for GP2040-CE is based on an official RaspBerry Pi Pico. That pinout can be found HERE. This can be found in the Releases section under Pico.
In addition to the default UF2 we also offer pre-compiled UF2s from community members that have verified its operation with their own devices. Some of these additional configurations include:
The instructions will slightly vary based on your device. These instructions are for a Raspberry Pi Pico.
If the device has been previously used for something other than GP2040-CE, please flash this file first to clear the on-board storage: flash_nuke.uf2. After flashing the nuke file, wait a minute for the clear program to run and the RPI-RP2 drive to reappear.
- Download the latest
GP2040-CE.uf2
file from the Releases section for your board (e.g.GP2040-CE-PicoFightingBoard_vX.X.X.uf2
for the Raspberry Pi Pico). - Unplug your Pico.
- Hold the BOOTSEL button on the Pico and plug into your computer. A new removable drive named
RPI-RP2
should appear in your file explorer. - Drag and drop the
GP2040-CE.uf2
file into the removable drive. This will flash the board. - The board is now running the GP2040-CE firmware and will appear as a controller on your computer.
If you would like to discuss features, issues or anything else related to GP2040 please create an issue or join the OpenStick GP2040-CE Discord channel.
Generally speaking, XInput will be the mode of choice for everything except Nintendo Switch and PlayStation 3. XInput mode is the most fully-featured, has the best compatibility with PC games, and is compatible with console adapters like the Brook Wingman product line. All things being equal, performance is the same in all modes.
GP2040-CE will work on PS4 games that implement support for legacy PS3 controllers. Many of the popular PS4 fighting games support them.
These consoles implement security measures that prevent unauthorized accessories from being used. The process of cracking or bypassing that security may not be legal everywhere. These consoles could be supported in the future if a user-friendly and completely legal implementation method is found.
Yes! Each GP2040-CE board is treated as a separate controller. However, be sure to only run the embedded web configurator for each controller one at a time.
Yes! If your platform supports 1000 Hz USB polling, input latency is less than 1ms. GP2040-CE is configured for 1000 Hz / 1 ms polling by default in all modes, however some systems override or ignore the polling rate the controller requests. The 1000 Hz polling rate is confirmed to work on PC and MiSTer. Even if your platform doesn't support high rate USB polling, GP2040-CE is still reading and processing your inputs as fast as the target system will allow.
No! GP2040-CE dedicates a processing core to just reading and writing player inputs. All secondary functions such as LEDs and displays are controlled by the secondary processor core. No matter how crazy the feature set becomes, GP2040-CE is unlikely to introduce any additional input latency.
GP2040-CE uses a generic system for handling button inputs that resembles a traditional PlayStation controller layout with a few extra buttons. This means 4 face buttons (B1-B4), 4 shoulder buttons (L1, L2, R1, R2), Select and Start (S1, S2), 2 stick buttons (L3, R3) and 2 auxiliary buttons for things like Home and Capture (A1, A2) on the Switch. The GP2040-CE documentation and web configurator have a dropdown to change the labels to more familiar controller layouts. You can refer to the button mapping table on the GP2040 Usage page.
There's no magic here, just some useful libraries working together:
- Single page application using React and Bootstrap is embedded in the GP2040-CE firmware
- TinyUSB library provides virtual network connection over USB via RNDIS
- lwIP library provides an HTTP server for the embedded React app and the web configuration API
- ArduinoJson library is used for serialization and deserialization of web API requests
Want to help improve GP2040-CE? There are a bunch of ways to contribute!
Pull requests are welcome and encouraged for enhancements, bug fixes and documentation updates.
Please respect the coding style of the file(s) you are working in, and enforce the use of the .editorconfig
file when present.
Join the OpenStick GP2040-CE channel to participate!
- FeralAI for building GP2040 and laying the foundation for this community project
- Ha Thach's excellent TinyUSB library examples
- fluffymadness's tinyusb-xinput sample
- Kevin Boone's blog post on using RP2040 flash memory as emulated EEPROM
- bitbank2 for the OneBitDisplay and BitBang_I2C libraries, which were ported for use with the Pico SDK
- arntsonl for the amazing cleanup and feature additions that brought us to v0.5.0
- alirin222 for the awesome turbo code (@alirin222 on Twitter)
- [DeBug] for improvments to the web-UI and fixing the PS3 homebutton issue
- TheTrain and Fortinbra for helping keep our community chugging along