Browse Source

Add switchusb output for controlling Nintendo Switch

master
Travis Burtrum 2 years ago
parent
commit
83bda3c95c
  1. 7
      hwids/switch.py
  2. 43
      platformio.ini
  3. 4
      readme.md
  4. 6
      src/Debug.cpp
  5. 5
      src/Playstation.cpp
  6. 13
      src/SnesNes.cpp
  7. 4
      src/gamepad/Gamepad.h
  8. 63
      src/gamepad/Switch-USB-Gamepad/SwitchUsbGamepad.h
  9. 87
      src/gamepad/common.h

7
hwids/switch.py

@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
Import("env")
board_config = env.BoardConfig()
# should be array of VID:PID pairs
board_config.update("build.hwids", [
["0x0f0d", "0x00c1"], # Hori Co., Ltd HORIPAD for Nintendo Switch
])

43
platformio.ini

@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
# supported values:
# $board: micro, esp32
# $input: snes, genesis, psx, n64, radio, debug
# $output: radio, usb, usbradio, bt, debug
# $output: radio, usb, usbradio, bt, switchusb, debug
# please note not all boards are compatible with all inputs/outputs
# for example esp32 can only do bt
# micro can only do radio or usb
@ -67,11 +67,12 @@ extends = out-usb, out-radio @@ -67,11 +67,12 @@ extends = out-usb, out-radio
build_flags = -DGAMEPAD_OUTPUT=4
src_filter = ${out-usb.src_filter} ${out-radio.src_filter}
[out-switch]
build_flags = -DGAMEPAD_OUTPUT=5
src_filter = +<gamepad/ESP32-BLE-Gamepad>
# from https://github.com/NathanReeves/BlueCubeMod#build-instructionsv2
platform_packages = framework-espidf @ https://github.com/OpenRetroPad/esp-idf
[out-switchusb]
# switch only supports 1 controller per dongle
build_flags = -DGAMEPAD_OUTPUT=5 -DGAMEPAD_COUNT=1
src_filter = +<gamepad/Switch-USB-Gamepad>
lib_deps = https://github.com/OpenRetroPad/HID
extra_scripts = pre:hwids/switch.py
# radio input
@ -101,6 +102,12 @@ extends = micro, in-radio, out-debug @@ -101,6 +102,12 @@ extends = micro, in-radio, out-debug
src_filter = ${in-radio.src_filter} ${out-debug.src_filter}
build_flags = ${in-radio.build_flags} ${out-debug.build_flags}
[env:micro-radio-switchusb]
extends = micro, in-radio, out-switchusb
src_filter = ${in-radio.src_filter} ${out-switchusb.src_filter}
build_flags = ${in-radio.build_flags} ${out-switchusb.build_flags}
lib_deps = ${in-radio.lib_deps}, ${out-switchusb.lib_deps}
# not enough pins for env:micro-radio-radio , plus it'd be crazy
# snes input
@ -139,6 +146,11 @@ extends = micro, in-snes, out-usbradio @@ -139,6 +146,11 @@ extends = micro, in-snes, out-usbradio
src_filter = ${in-snes.src_filter} ${out-usbradio.src_filter}
build_flags = ${in-snes.build_flags} ${out-usbradio.build_flags}
[env:micro-snes-switchusb]
extends = micro, in-snes, out-switchusb
src_filter = ${in-snes.src_filter} ${out-switchusb.src_filter}
build_flags = ${in-snes.build_flags} ${out-switchusb.build_flags}
# n64 input
[in-n64]
@ -176,6 +188,11 @@ extends = micro, in-n64, out-usbradio @@ -176,6 +188,11 @@ extends = micro, in-n64, out-usbradio
src_filter = ${in-n64.src_filter} ${out-usbradio.src_filter}
build_flags = ${in-n64.build_flags} ${out-usbradio.build_flags}
[env:micro-n64-switchusb]
extends = micro, in-n64, out-switchusb
src_filter = ${in-n64.src_filter} ${out-switchusb.src_filter}
build_flags = ${in-n64.build_flags} ${out-switchusb.build_flags}
# genesis input
[in-genesis]
@ -215,6 +232,11 @@ extends = micro, in-genesis, out-usbradio @@ -215,6 +232,11 @@ extends = micro, in-genesis, out-usbradio
src_filter = ${in-genesis.src_filter} ${out-usbradio.src_filter}
build_flags = ${in-genesis.build_flags} ${out-usbradio.build_flags} -DGAMEPAD_COUNT=1
[env:micro-genesis-switchusb]
extends = micro, in-genesis, out-switchusb
src_filter = ${in-genesis.src_filter} ${out-switchusb.src_filter}
build_flags = ${in-genesis.build_flags} ${out-switchusb.build_flags}
# psx input
[in-psx]
@ -251,6 +273,11 @@ extends = micro, in-psx, out-usbradio @@ -251,6 +273,11 @@ extends = micro, in-psx, out-usbradio
src_filter = ${in-psx.src_filter} ${out-usbradio.src_filter}
build_flags = ${in-psx.build_flags} ${out-usbradio.build_flags}
[env:micro-psx-switchusb]
extends = micro, in-psx, out-switchusb
src_filter = ${in-psx.src_filter} ${out-switchusb.src_filter}
build_flags = ${in-psx.build_flags} ${out-switchusb.build_flags}
# debug input
[in-debug]
@ -287,3 +314,7 @@ extends = micro, in-debug, out-usbradio @@ -287,3 +314,7 @@ extends = micro, in-debug, out-usbradio
src_filter = ${in-debug.src_filter} ${out-usbradio.src_filter}
build_flags = ${in-debug.build_flags} ${out-usbradio.build_flags}
[env:micro-debug-switchusb]
extends = micro, in-debug, out-switchusb
src_filter = ${in-debug.src_filter} ${out-switchusb.src_filter}
build_flags = ${in-debug.build_flags} ${out-switchusb.build_flags}

4
readme.md

@ -9,7 +9,7 @@ env's are laid out like `$board-$input-$output` @@ -9,7 +9,7 @@ env's are laid out like `$board-$input-$output`
supported values:
* $board: micro, esp32
* $input: snes, genesis, psx, n64, radio, debug
* $output: radio, usb, usbradio, bt, debug
* $output: radio, usb, usbradio, switchusb, bt, debug
* please note not all boards are compatible with all inputs/outputs, for example esp32 can only do bt, micro can only do radio or usb
Credits / Links
@ -21,7 +21,9 @@ Code and/or inspiration was (or will be) taken from these places, in no particul @@ -21,7 +21,9 @@ Code and/or inspiration was (or will be) taken from these places, in no particul
* [DaemonBite-Retro-Controllers-USB](https://github.com/MickGyver/DaemonBite-Retro-Controllers-USB)
* [Arduino-USB-HID-RetroJoystickAdapter](https://github.com/mcgurk/Arduino-USB-HID-RetroJoystickAdapter)
* [BlueCubeMod](https://github.com/NathanReeves/BlueCubeMod)
* [OpenSwitchPad](https://github.com/agustincampeny/OpenSwitchPad)
* [arduino-n64-controller-library](https://github.com/pothos/arduino-n64-controller-library)
* [N64toiQue](https://github.com/mnzlmstr/N64toiQue)
* [dreamcast_usb](https://github.com/raphnet/dreamcast_usb)
* [SNES-NRF24](https://github.com/baldengineer/SNES-NRF24)
* https://github.com/NicoHood/Nintendo

6
src/Debug.cpp

@ -16,9 +16,9 @@ void setup() { @@ -16,9 +16,9 @@ void setup() {
void loop() {
if (gamepad.isConnected()) {
// test code to automate sending to test RadioReceiver (or any gamepad impl)
Serial.println("Press buttons 1 and 32. Move all axes to center. Set DPAD to down right.");
gamepad.press(c, BUTTON_1);
gamepad.press(c, BUTTON_32);
Serial.println("Press buttons A and Y. Move all axes to center. Set DPAD to down right.");
gamepad.press(c, BUTTON_A);
gamepad.press(c, BUTTON_Y);
gamepad.setAxis(c, 0, 0, 0, 0, 0, 0, DPAD_DOWN_RIGHT);
delay(500);
Serial.println("Release all buttons. Move all axes to center. Set DPAD to center.");

5
src/Playstation.cpp

@ -167,7 +167,8 @@ class Joystick_ { @@ -167,7 +167,8 @@ class Joystick_ {
int16_t translateAxis(uint8_t v) {
//map(value, fromLow, fromHigh, toLow, toHigh)
return v == 128 ? 0 : map(v, 0, 255, -32767, 32767);
// todo: don't map at all if translation isn't required...
return v == 128 ? AXIS_CENTER : map(v, 0, 255, AXIS_MIN, AXIS_MAX);
}
void sendState(uint8_t c) {
@ -322,5 +323,5 @@ void loop() { @@ -322,5 +323,5 @@ void loop() {
Joystick[i].updateState(i);
}
delayMicroseconds(1000);
delayMicroseconds(500); // todo: proper value for this... does it depend on number of gamepads/multitap ?
}

13
src/SnesNes.cpp

@ -7,7 +7,18 @@ @@ -7,7 +7,18 @@
#define BUTTON_COUNT 12 // SNES has 12, NES only has 8
//individual data pin for each controller
static const int DATA_PIN[GAMEPAD_COUNT] = {18, 19}; // grey, 20, 21 are the next logical ones
static const int DATA_PIN[GAMEPAD_COUNT] = {
18,
#if GAMEPAD_COUNT > 1
19,
#endif
#if GAMEPAD_COUNT > 2
20,
#endif
#if GAMEPAD_COUNT > 3
21,
#endif
};
//shared pins between all controllers
#if defined(CONFIG_BT_ENABLED)

4
src/gamepad/Gamepad.h

@ -39,6 +39,10 @@ @@ -39,6 +39,10 @@
#include "UsbRadio-Gamepad/UsbRadioGamepad.h"
#elif GAMEPAD_OUTPUT == 5
#include "Switch-USB-Gamepad/SwitchUsbGamepad.h"
#else
#error Unsupported value for GAMEPAD_OUTPUT, must be 0-3

63
src/gamepad/Switch-USB-Gamepad/SwitchUsbGamepad.h

@ -0,0 +1,63 @@ @@ -0,0 +1,63 @@
#ifndef SWITCH_USB_GAMEPAD_H
#define SWITCH_USB_GAMEPAD_H
#ifndef GAMEPAD_CLASS
#define GAMEPAD_CLASS SwitchUsbGamepad
#endif
#include "../common.h"
#include "HID-Project.h"
class SwitchUsbGamepad : public AbstractGamepad {
public:
SwitchUsbGamepad() : AbstractGamepad() {
}
virtual void begin(void) {
NSGamepad.begin();
}
virtual void end(void) {
NSGamepad.end();
}
virtual void setAxis(const uint8_t cIdx, int16_t x, int16_t y, int16_t z, int16_t rZ, char rX, char rY, signed char hat) {
// Move x/y Axis to a new position (16bit)
NSGamepad.leftXAxis(x);
NSGamepad.leftYAxis(y);
NSGamepad.rightXAxis(z);
NSGamepad.rightYAxis(rZ);
NSGamepad.dPad(hat);
this->sync(cIdx);
}
virtual void setHatSync(const uint8_t cIdx, signed char hat) {
setAxis(cIdx, 0, 0, 0, 0, 0, 0, hat);
}
virtual void buttons(const uint8_t cIdx, uint32_t b) {
NSGamepad.buttons(b);
}
virtual void press(const uint8_t cIdx, uint32_t b) {
NSGamepad.press(b);
}
virtual void release(const uint8_t cIdx, uint32_t b) {
NSGamepad.release(b);
}
virtual void sync(const uint8_t cIdx) {
// todo: something to make this play nice with radio
sendHidReport(cIdx, &gamepadReport, GAMEPAD_REPORT_LEN);
}
virtual void sendHidReport(const uint8_t cIdx, const void* d, int len) {
//gamepad[cIdx].send(d, len);]]
NSGamepad.write();
}
};
#endif // SWITCH_USB_GAMEPAD_H

87
src/gamepad/common.h

@ -7,28 +7,83 @@ @@ -7,28 +7,83 @@
#define ARDUINO_ARCH_ESP32 1
#include "HIDTypes.h"
#if GAMEPAD_OUTPUT == 5 // nintendo switch
#define BUTTON_A NSButton_A
#define BUTTON_B NSButton_B
#define BUTTON_MENU NSButton_Home
#define BUTTON_X NSButton_X
#define BUTTON_Y NSButton_Y
#define BUTTON_TL NSButton_LeftTrigger
#define BUTTON_TR NSButton_RightTrigger
#define BUTTON_TL2 NSButton_LeftThrottle
#define BUTTON_TR2 NSButton_RightThrottle
#define BUTTON_SELECT NSButton_Minus
#define BUTTON_START NSButton_Plus
#define BUTTON_THUMBL NSButton_LeftStick
#define BUTTON_THUMBR NSButton_RightStick
#define DPAD_CENTER NSGAMEPAD_DPAD_CENTERED
#define DPAD_UP NSGAMEPAD_DPAD_UP
#define DPAD_UP_RIGHT NSGAMEPAD_DPAD_UP_RIGHT
#define DPAD_RIGHT NSGAMEPAD_DPAD_RIGHT
#define DPAD_DOWN_RIGHT NSGAMEPAD_DPAD_DOWN_RIGHT
#define DPAD_DOWN NSGAMEPAD_DPAD_DOWN
#define DPAD_DOWN_LEFT NSGAMEPAD_DPAD_DOWN_LEFT
#define DPAD_LEFT NSGAMEPAD_DPAD_LEFT
#define DPAD_UP_LEFT NSGAMEPAD_DPAD_UP_LEFT
#define AXIS_CENTER 128
#define AXIS_MAX 255
#define AXIS_MIN 0
#else
#define BUTTON_A 1
#define BUTTON_B 2
#define BUTTON_MENU 4
#define BUTTON_X 8
#define BUTTON_Y 16
#define BUTTON_TL 64
#define BUTTON_L 64
#define BUTTON_L1 64
#define BUTTON_TR 128
#define BUTTON_R 128
#define BUTTON_R1 128
#define BUTTON_TL2 256
#define BUTTON_L2 256
#define BUTTON_TR2 512
#define BUTTON_R2 512
#define BUTTON_SELECT 1024
#define BUTTON_START 2048
#define BUTTON_THUMBL 8192
#define BUTTON_L3 8192
#define BUTTON_THUMBR 16384
#define BUTTON_R3 16384
#define DPAD_CENTER 0
#define DPAD_UP 1
#define DPAD_UP_RIGHT 2
#define DPAD_RIGHT 3
#define DPAD_DOWN_RIGHT 4
#define DPAD_DOWN 5
#define DPAD_DOWN_LEFT 6
#define DPAD_LEFT 7
#define DPAD_UP_LEFT 8
#define AXIS_CENTER 0
#define AXIS_MAX 32768
#define AXIS_MIN -32767
#endif // nintendo switch
// aliases
#define BUTTON_HOME BUTTON_MENU
#define BUTTON_L BUTTON_TL
#define BUTTON_L1 BUTTON_TL
#define BUTTON_R BUTTON_TR
#define BUTTON_R1 BUTTON_TR
#define BUTTON_L2 BUTTON_TL2
#define BUTTON_R2 BUTTON_TR2
#define BUTTON_L3 BUTTON_THUMBL
#define BUTTON_R3 BUTTON_THUMBR
#define DPAD_CENTERED DPAD_CENTER
// end aliases
#if 0
#define BUTTON_1 1
#define BUTTON_2 2
#define BUTTON_3 4
@ -61,21 +116,7 @@ @@ -61,21 +116,7 @@
#define BUTTON_30 536870912
#define BUTTON_31 1073741824
#define BUTTON_32 2147483648
#define DPAD_CENTER 0
#define DPAD_CENTERED 0
#define DPAD_UP 1
#define DPAD_UP_RIGHT 2
#define DPAD_RIGHT 3
#define DPAD_DOWN_RIGHT 4
#define DPAD_DOWN 5
#define DPAD_DOWN_LEFT 6
#define DPAD_LEFT 7
#define DPAD_UP_LEFT 8
#define AXIS_CENTER 0
#define AXIS_MAX 32768
#define AXIS_MIN -32767
#endif
#ifndef GAMEPAD_REPORT_ARRAY_ADD
// this is used by radio gamepad to send additional info

Loading…
Cancel
Save