diff --git a/hwids/switch.py b/hwids/switch.py new file mode 100644 index 0000000..f5228f0 --- /dev/null +++ b/hwids/switch.py @@ -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 +]) diff --git a/platformio.ini b/platformio.ini index bfe5f08..7eb7724 100644 --- a/platformio.ini +++ b/platformio.ini @@ -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 build_flags = -DGAMEPAD_OUTPUT=4 src_filter = ${out-usb.src_filter} ${out-radio.src_filter} -[out-switch] -build_flags = -DGAMEPAD_OUTPUT=5 -src_filter = + -# 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 = + +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 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 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 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 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 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 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} diff --git a/readme.md b/readme.md index 1172779..673bebe 100644 --- a/readme.md +++ b/readme.md @@ -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 * [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 diff --git a/src/Debug.cpp b/src/Debug.cpp index 1d0f3fb..e464e71 100644 --- a/src/Debug.cpp +++ b/src/Debug.cpp @@ -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."); diff --git a/src/Playstation.cpp b/src/Playstation.cpp index 6934b40..68879b3 100644 --- a/src/Playstation.cpp +++ b/src/Playstation.cpp @@ -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() { Joystick[i].updateState(i); } - delayMicroseconds(1000); + delayMicroseconds(500); // todo: proper value for this... does it depend on number of gamepads/multitap ? } diff --git a/src/SnesNes.cpp b/src/SnesNes.cpp index 1fba631..a40206a 100644 --- a/src/SnesNes.cpp +++ b/src/SnesNes.cpp @@ -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) diff --git a/src/gamepad/Gamepad.h b/src/gamepad/Gamepad.h index 0465879..b89eeff 100644 --- a/src/gamepad/Gamepad.h +++ b/src/gamepad/Gamepad.h @@ -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 diff --git a/src/gamepad/Switch-USB-Gamepad/SwitchUsbGamepad.h b/src/gamepad/Switch-USB-Gamepad/SwitchUsbGamepad.h new file mode 100644 index 0000000..1da414d --- /dev/null +++ b/src/gamepad/Switch-USB-Gamepad/SwitchUsbGamepad.h @@ -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 diff --git a/src/gamepad/common.h b/src/gamepad/common.h index f980e6d..00a7679 100644 --- a/src/gamepad/common.h +++ b/src/gamepad/common.h @@ -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 @@ #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