knflrpn/2wiCC

Procon Controller (SwiCC v2)

C

31

28 commits

updated Sep 13, 2026

See the code

README

2wiCC -- Switch Controller Controller (SwiCC) v2

Nintendo Switch Controller Emulator for RP2040/RP2350.

2wiCC (SwiCC v2) is a controller emulator that presents itself as a Switch (1) Pro Controller to the console while providing control from a PC via UART commands.

Hardware Requirements

Any RP2040- or RP2350-based board should work, potentially with pin configuration changes. This project has been written assuming a Waveshare RP2040-Zero board, which is ideal because of its small size, onboard RGB LED, and USB-C connector.

A serial (UART) adapter is needed. This project has been written assuming that a second RP2040-Zero board has been configured as a USB-serial adapter using the firmware available at https://github.com/knflrpn/2wiCC_Comms/releases .

Switch Settings

On your Switch, you need to go to Settings > Controllers & Accessories and check "Nintendo Switch Pro Controller Wired Communication" to force the Switch to use USB for USB-connected controllers, otherwise the Switch will only use USB to exchange Bluetooth information and then stop talking over USB.

Connections

FunctionGPIO PinNotes
UART TX0 (default)Serial output from board
UART RX1 (default)Serial input to board
Status LED16WS2812 RGB LED (onboard on RP2040-Zero)
VSYNC Input14Optional: for frame synchronization

Assembly Options

  1. Flash one board with this firmware.
  2. Flash a second board with the USB-UART bridge firmware (https://github.com/knflrpn/2wiCC_Comms/releases).
  3. Cross-wire the UART pins (TX→RX, RX→TX) between the two boards.
  4. Connect grounds between the two boards.

Internals

A case for this setup is available here: https://www.printables.com/model/1401073-2wicc-case

Option 2: Direct Connection

Connect SwiCC to your host system via a UART-to-USB adapter of your choice.

  • Baud Rate: 460,800 bps
  • Format: 8N1 (8 data bits, no parity, 1 stop bit)
  • Flow Control: None

LED Status Indicator

The RGB LED provides visual feedback:

  • Red pulse (heartbeat): Indicator that SwiCC is alive
  • Steady blue: USB connection established

If the heartbeat is present but there is no steady blue, it indicates that the SwiCC is alive but the Switch is not talking to it, which is most often because of the USB cable (e.g. using a 'charging only' cable that doesn't carry data).

Command Reference

All commands are sent in ASCII and consist of

  1. A + character to indicate the start of a command.
  2. A command type consisting of one or more alphanumeric characters.
  3. A space character to indicate the end of the command type string. All commands must include this space even if the command does not require a parameter.
  4. An optional parameter (depending on the command).
  5. A newline (either \r or \n or both) to commit the command.

Controller Input Commands

CommandParameterDescription
QD6 hex digitsQueue digital-only controller state (3 bytes)
QF18 hex digitsQueue full controller state (9 bytes: 3 digital + 6 analog)
QFI42 hex digitsFull controller state (QF) plus IMU data

Controller State Format:

Controller state is sent as hex-encoded ASCII. E.g. a byte with decimal value 255 is sent as the two ASCII characters FF.

  • Digital (3 bytes): Button states as a bitmask
    • First byte: [ZR, R, Right SL, Right SR, A, B, X, Y] (bits 7-0)
    • Second byte: [unused, unused, Capture, Home, Left Stick, Right Stick, +, -] (bits 7-0)
    • Third byte: [ZL, L, Left SL, Left SR, D-pad Left, D-pad Right, D-pad Up, D-pad Down] (bits 7-0)
  • Analog (6 bytes): Left stick X, Y, Right stick X, Y, encoded in the Pro Controller data format (see https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/bluetooth_hid_notes.md). Center position is defined as 0x800 and full swing is +/- 0x600 from center.
  • IMU (12 bytes): 16-bit little-endian 2's complement signed value each for X, Y, Z acceleration and X, Y, Z gyro, in that order. Neutral for all values is 0.

Note that IMU state is not queued; it takes effect immediately after QFI is parsed, and persists until the next QFI.

Playback Mode Commands

CommandParameterDescription
SPMRT or BUFSet playback mode (Real-Time or Buffered)

Queue Management Commands

CommandParameterDescription
GQRNoneGet queue remaining space
GQSNoneGet total queue size (default 1024)

Synchronization Commands

CommandParameterDescription
VSYNC0 or 1Disable/enable VSYNC synchronization
VSD4 hex digitsSet frame delay in microseconds (0000-FFFF)

Recording Commands

CommandParameterDescription
REC0 or 1Stop/start input recording
GRRNoneGet recording buffer remaining space
GRSNoneGet total recording buffer size (default 1024)
GR0 or 1Get recorded data (0=start from beginning, 1=continue)

System Commands

CommandParameterDescription
IDNoneReturns +2wiCC (device identification)
VERNoneReturns firmware version
GCSNoneGet USB connection status (0=disconnected, 1=connected)
LED0 or 1Disable/enable status LED
RMBL0 or 1Disable/enable rumble feedback
ECHOtextEcho back the provided text

Playback Modes

Real-Time Mode (SPM RT)

  • Always uses the most recently received controller state
  • Best for live input injection

Buffered Mode (SPM BUF)

  • Plays controller states sequentially from the queue
  • Advances one state per frame (60 FPS if VSYNC disabled, otherwise according to VSYNC)
  • Automatically switches back to real-time if buffer runs empty

Usage Examples

Basic Controller Input

+QD 080000    # Press A button
+QD 000000    # Release all buttons

Controller State with Analog Sticks

+QF 000000000880000880    # No buttons and neutral sticks

Recording Workflow

+REC 1                    # Start recording
# Play the game...
+REC 0                    # Stop recording
+GR 0                     # Download recorded inputs

Repeat +GR 1 until the entire recording is retrieved.

Recording Format

Recorded inputs use run-length encoding and are returned in this format:

+R [18 hex digits]x[2 hex digits]
  • 18 hex digits: Full controller state (9 bytes)
  • x: Separator (literal x character)
  • 2 hex digits: Number of consecutive frames with this state (1-240)

Example: +R 000000000880000880x74 means neutral controller for 0x74 (116 decimal) frames.

Status and Error Messages

SwiCC sends status updates back to the host PC over the UART connection. The format for these messages is a + character to mark the beginning of a message, an alphanumeric message type string, a space character, optional data, and a newline (\r\n) to mark the end of the message.

Message FormatDescription
+ERR WATCHDOGIndicates the microcontroller rebooted because the watchdog timer timed out.
+RMBL [6 hex digits]Rumble data sent from the Switch. Rumble feedback defaults to disabled and must be enabled with the RMBL command if desired.
+LGHT [2 hex digits]Reports a change to the controller's indicator lights.
+WRN TIMEOUT [0 or 1]Warning indicating whether the Switch has enabled (1) or disabled (0) USB timeout 4. If USB timeout remains enabled, the console will stop communicating over USB. See the Switch Settings section above to prevent this.

knflrpn/2wiCC

Procon Controller (SwiCC v2)

C

31

28 commits

updated Sep 13, 2026

See the code

README

2wiCC -- Switch Controller Controller (SwiCC) v2

Nintendo Switch Controller Emulator for RP2040/RP2350.

2wiCC (SwiCC v2) is a controller emulator that presents itself as a Switch (1) Pro Controller to the console while providing control from a PC via UART commands.

Hardware Requirements

Any RP2040- or RP2350-based board should work, potentially with pin configuration changes. This project has been written assuming a Waveshare RP2040-Zero board, which is ideal because of its small size, onboard RGB LED, and USB-C connector.

A serial (UART) adapter is needed. This project has been written assuming that a second RP2040-Zero board has been configured as a USB-serial adapter using the firmware available at https://github.com/knflrpn/2wiCC_Comms/releases .

Switch Settings

On your Switch, you need to go to Settings > Controllers & Accessories and check "Nintendo Switch Pro Controller Wired Communication" to force the Switch to use USB for USB-connected controllers, otherwise the Switch will only use USB to exchange Bluetooth information and then stop talking over USB.

Connections

FunctionGPIO PinNotes
UART TX0 (default)Serial output from board
UART RX1 (default)Serial input to board
Status LED16WS2812 RGB LED (onboard on RP2040-Zero)
VSYNC Input14Optional: for frame synchronization

Assembly Options

  1. Flash one board with this firmware.
  2. Flash a second board with the USB-UART bridge firmware (https://github.com/knflrpn/2wiCC_Comms/releases).
  3. Cross-wire the UART pins (TX→RX, RX→TX) between the two boards.
  4. Connect grounds between the two boards.

Internals

A case for this setup is available here: https://www.printables.com/model/1401073-2wicc-case

Option 2: Direct Connection

Connect SwiCC to your host system via a UART-to-USB adapter of your choice.

  • Baud Rate: 460,800 bps
  • Format: 8N1 (8 data bits, no parity, 1 stop bit)
  • Flow Control: None

LED Status Indicator

The RGB LED provides visual feedback:

  • Red pulse (heartbeat): Indicator that SwiCC is alive
  • Steady blue: USB connection established

If the heartbeat is present but there is no steady blue, it indicates that the SwiCC is alive but the Switch is not talking to it, which is most often because of the USB cable (e.g. using a 'charging only' cable that doesn't carry data).

Command Reference

All commands are sent in ASCII and consist of

  1. A + character to indicate the start of a command.
  2. A command type consisting of one or more alphanumeric characters.
  3. A space character to indicate the end of the command type string. All commands must include this space even if the command does not require a parameter.
  4. An optional parameter (depending on the command).
  5. A newline (either \r or \n or both) to commit the command.

Controller Input Commands

CommandParameterDescription
QD6 hex digitsQueue digital-only controller state (3 bytes)
QF18 hex digitsQueue full controller state (9 bytes: 3 digital + 6 analog)
QFI42 hex digitsFull controller state (QF) plus IMU data

Controller State Format:

Controller state is sent as hex-encoded ASCII. E.g. a byte with decimal value 255 is sent as the two ASCII characters FF.

  • Digital (3 bytes): Button states as a bitmask
    • First byte: [ZR, R, Right SL, Right SR, A, B, X, Y] (bits 7-0)
    • Second byte: [unused, unused, Capture, Home, Left Stick, Right Stick, +, -] (bits 7-0)
    • Third byte: [ZL, L, Left SL, Left SR, D-pad Left, D-pad Right, D-pad Up, D-pad Down] (bits 7-0)
  • Analog (6 bytes): Left stick X, Y, Right stick X, Y, encoded in the Pro Controller data format (see https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/bluetooth_hid_notes.md). Center position is defined as 0x800 and full swing is +/- 0x600 from center.
  • IMU (12 bytes): 16-bit little-endian 2's complement signed value each for X, Y, Z acceleration and X, Y, Z gyro, in that order. Neutral for all values is 0.

Note that IMU state is not queued; it takes effect immediately after QFI is parsed, and persists until the next QFI.

Playback Mode Commands

CommandParameterDescription
SPMRT or BUFSet playback mode (Real-Time or Buffered)

Queue Management Commands

CommandParameterDescription
GQRNoneGet queue remaining space
GQSNoneGet total queue size (default 1024)

Synchronization Commands

CommandParameterDescription
VSYNC0 or 1Disable/enable VSYNC synchronization
VSD4 hex digitsSet frame delay in microseconds (0000-FFFF)

Recording Commands

CommandParameterDescription
REC0 or 1Stop/start input recording
GRRNoneGet recording buffer remaining space
GRSNoneGet total recording buffer size (default 1024)
GR0 or 1Get recorded data (0=start from beginning, 1=continue)

System Commands

CommandParameterDescription
IDNoneReturns +2wiCC (device identification)
VERNoneReturns firmware version
GCSNoneGet USB connection status (0=disconnected, 1=connected)
LED0 or 1Disable/enable status LED
RMBL0 or 1Disable/enable rumble feedback
ECHOtextEcho back the provided text

Playback Modes

Real-Time Mode (SPM RT)

  • Always uses the most recently received controller state
  • Best for live input injection

Buffered Mode (SPM BUF)

  • Plays controller states sequentially from the queue
  • Advances one state per frame (60 FPS if VSYNC disabled, otherwise according to VSYNC)
  • Automatically switches back to real-time if buffer runs empty

Usage Examples

Basic Controller Input

+QD 080000    # Press A button
+QD 000000    # Release all buttons

Controller State with Analog Sticks

+QF 000000000880000880    # No buttons and neutral sticks

Recording Workflow

+REC 1                    # Start recording
# Play the game...
+REC 0                    # Stop recording
+GR 0                     # Download recorded inputs

Repeat +GR 1 until the entire recording is retrieved.

Recording Format

Recorded inputs use run-length encoding and are returned in this format:

+R [18 hex digits]x[2 hex digits]
  • 18 hex digits: Full controller state (9 bytes)
  • x: Separator (literal x character)
  • 2 hex digits: Number of consecutive frames with this state (1-240)

Example: +R 000000000880000880x74 means neutral controller for 0x74 (116 decimal) frames.

Status and Error Messages

SwiCC sends status updates back to the host PC over the UART connection. The format for these messages is a + character to mark the beginning of a message, an alphanumeric message type string, a space character, optional data, and a newline (\r\n) to mark the end of the message.

Message FormatDescription
+ERR WATCHDOGIndicates the microcontroller rebooted because the watchdog timer timed out.
+RMBL [6 hex digits]Rumble data sent from the Switch. Rumble feedback defaults to disabled and must be enabled with the RMBL command if desired.
+LGHT [2 hex digits]Reports a change to the controller's indicator lights.
+WRN TIMEOUT [0 or 1]Warning indicating whether the Switch has enabled (1) or disabled (0) USB timeout 4. If USB timeout remains enabled, the console will stop communicating over USB. See the Switch Settings section above to prevent this.