diff --git a/platformio.ini b/platformio.ini index 587a589..2fe8f66 100644 --- a/platformio.ini +++ b/platformio.ini @@ -10,13 +10,6 @@ # env's are laid out like: # $board-$input-$output -# supported values: -# $board: micro, esp32 -# $input: snes, genesis, psx, n64, gc, radio, 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 # CODE_PLATFORM == 0: generic, should work on anything # CODE_PLATFORM == 1: optimized for esp32 @@ -373,6 +366,52 @@ extends = micro, in-saturn, out-switchusb src_filter = ${in-saturn.src_filter} ${out-switchusb.src_filter} build_flags = ${in-saturn.build_flags} ${out-switchusb.build_flags} + +# wii input + +[in-wii] +src_filter = -<*> + +build_flags = ${common.build_flags} -DGAMEPAD_INPUT=7 -DGAMEPAD_COUNT=1 +lib_deps = dmadison/Nintendo Extension Ctrl @ 0.8.1 + +[env:esp32-wii-bt] +extends = esp32, in-wii, out-bt +src_filter = ${in-wii.src_filter} ${out-bt.src_filter} +build_flags = ${in-wii.build_flags} ${out-bt.build_flags} + +[env:esp32-wii-debug] +extends = esp32, in-wii, out-debug +src_filter = ${in-wii.src_filter} ${out-debug.src_filter} +build_flags = ${in-wii.build_flags} ${out-debug.build_flags} + +[env:micro-wii-usb] +extends = micro, in-wii, out-usb +src_filter = ${in-wii.src_filter} ${out-usb.src_filter} +build_flags = ${in-wii.build_flags} ${out-usb.build_flags} + +[env:micro-wii-debug] +extends = micro, in-wii, out-debug +src_filter = ${in-wii.src_filter} ${out-debug.src_filter} +build_flags = ${in-wii.build_flags} ${out-debug.build_flags} + +[env:micro-wii-radio] +extends = micro, in-wii, out-radio +src_filter = ${in-wii.src_filter} ${out-radio.src_filter} +build_flags = ${in-wii.build_flags} ${out-radio.build_flags} +lib_deps = ${in-wii.lib_deps}, ${out-radio.lib_deps} + +[env:micro-wii-usbradio] +extends = micro, in-wii, out-usbradio +src_filter = ${in-wii.src_filter} ${out-usbradio.src_filter} +build_flags = ${in-wii.build_flags} ${out-usbradio.build_flags} +lib_deps = ${in-wii.lib_deps}, ${out-usbradio.lib_deps} + +[env:micro-wii-switchusb] +extends = micro, in-wii, out-switchusb +src_filter = ${in-wii.src_filter} ${out-switchusb.src_filter} +build_flags = ${in-wii.build_flags} ${out-switchusb.build_flags} +lib_deps = ${in-wii.lib_deps}, ${out-switchusb.lib_deps} + # debug input [in-debug] diff --git a/readme.md b/readme.md index 6a91269..93f3cdd 100644 --- a/readme.md +++ b/readme.md @@ -3,7 +3,7 @@ OpenRetroPad Adapt various input devices to various output devices. -Currently supported inputs: SNES/NES, Sega Genesis/Megadrive/Atari, Playstation (and PS2) Digital and Dual shock, Nintendo 64, Nintendo Gamecube +Currently supported inputs: SNES/NES, Sega Genesis/Megadrive/Atari, Sega Saturn, Playstation (and PS2) Digital and Dual shock, Nintendo 64, Nintendo Gamecube, Nintendo Wii Nunchuck/Wii Classic/SNES+NES Mini Currently supported outputs: bluetooth-hid gamepad, usb-hid gamepad, nintendo switch usb gamepad, wireless usb-hid gamepad over radio @@ -14,7 +14,7 @@ Build using [PlatformIO](https://platformio.org/) using `pio run` or `pio run -e env's are laid out like `$board-$input-$output` supported values: * $board: micro, esp32 - * $input: snes, genesis, saturn, psx, n64, gc, radio, debug + * $input: snes, genesis, saturn, psx, n64, gc, wii, radio, 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 @@ -33,35 +33,36 @@ Wiring ![DB-25 Pinout](images/db25pins.jpg) -| DB-25 Pins | Arduino Pro Micro GPIO | ESP32 GPIO | Radio | SNES | PSX | N64 | Gamecube | Genesis | Dreamcast | Saturn | -|---------------|------------------------|------------|----------|---------|--------|----------|----------|-------------|-----------|-------------| -| 1 TX | 1 | 19 | - | LATCH | - | - | - | P1-1 | P1-DATA1 | P1-7 | -| 2 SDA | 2 | 21 | - | CLOCK | DATA | P1-DATA | P1-DATA | P1-3 | P1-DATA5 | P1-2 | -| 3 SCL | 3 | 22 | - | P1-DATA | CMD | - | - | P1-4 | - | P1-3 | -| 4 Analog | 4 | 15 | - | P2-DATA | ATT | - | - | P1-6 | - | P1-6 | -| 5 Digital | 5 | 16 | - | P3-DATA | CLK | - | - | P1-7 | - | | -| 6 Analog | 6 | 2 | - | P4-DATA | - | - | - | P1-9 | - | P2-6 | -| 7 Digital | 7 | 17 | CE | - | - | - | - | P2-7* | - | | -| 8 Analog | 8 | 4 | CSN | - | - | - | - | - | - | | -| 9 Analog | 9 > 1k Ω | 35 > 1k Ω | - | 330 Ω | 100 Ω | 220 Ω | 680 Ω | 470 Ω | 820 Ω | TODO | -| 10 Analog | 10 | 32 | - | - | - | - | - | - | - | | -| 11 RX | 0 | 18 | - | - | - | - | - | P1-2 | - | P1-8 | -| 12 - | - | - | - | - | - | - | - | - | - | | -| 13 - | - | - | - | - | - | - | - | - | - | | -| 14 MISO | 14 | 12 | MISO | - | - | - | - | P2-6* | - | PX-5 | -| 15 SCLK | 15 | 14 | SCLK | - | - | - | - | P2-9* | - | PX-4 | -| 16 MOSI | 16 | 13 | MOSI | - | - | - | - | - | - | | -| 17 - | - | - | - | - | - | - | - | - | - | | -| 18 Analog | 18 | 27 | - | - | - | - | - | P2-1 | - | P2-7 | -| 19 Analog | 19 | 26 | - | - | - | - | - | P2-2 | - | P2-8 | -| 20 Analog | 20 | 25 | - | - | - | - | - | P2-3 | - | P2-2 | -| 21 Analog | 21 | 33 | - | - | - | - | - | P2-4 | - | P2-3 | -| 22 - | - | - | - | - | - | - | - | - | - | | -| 23 3.3V VCC | - | 3.3V VCC | 3.3V VCC | - | - | 3.3V VCC | 3.3V VCC | - | - | | -| 24 5V VCC | 5V VCC OUT | 5V VCC | 5V VCC | 5V VCC | 5V VCC | - | 5V VCC | PX-5 5V VCC | 5V VCC | PX-1 5V VCC | -| 25 GND | GND | GND | GND | GND | - | GND | GND | PX-8 GND | GND | PX-9 GND | +| DB-25 Pins | Arduino Pro Micro GPIO | ESP32 GPIO | Radio | SNES | PSX | N64 | Gamecube | Genesis | Dreamcast | Saturn | Wii Ext | +|---------------|------------------------|------------|----------|---------|--------|----------|----------|-------------|-----------|-------------|----------| +| 1 TX | 1 | 19 | - | LATCH | - | - | - | P1-1 | P1-DATA1 | P1-7 | - | +| 2 SDA | 2 | 21 | - | CLOCK | DATA | P1-DATA | P1-DATA | P1-3 | P1-DATA5 | P1-2 | SDA | +| 3 SCL | 3 | 22 | - | P1-DATA | CMD | - | - | P1-4 | - | P1-3 | SCL | +| 4 Analog | 4 | 15 | - | P2-DATA | ATT | - | - | P1-6 | - | P1-6 | - | +| 5 Digital | 5 | 16 | - | P3-DATA | CLK | - | - | P1-7 | - | PX-5 | - | +| 6 Analog | 6 | 2 | - | P4-DATA | - | - | - | P1-9 | - | PX-4 | - | +| 7 Digital | 7 | 17 | CE | - | - | - | - | P2-7* | - | - | - | +| 8 Analog | 8 | 4 | CSN | - | - | - | - | - | - | - | - | +| 9 Analog | 9 > 1k Ω | 35 > 1k Ω | - | 330 Ω | 100 Ω | 220 Ω | 680 Ω | 470 Ω | 820 Ω | 1000 Ω | 1500 Ω | +| 10 Analog | 10 | 32 | - | - | - | - | - | - | - | P2-6 | - | +| 11 RX | 0 | 18 | - | - | - | - | - | P1-2 | - | P1-8 | - | +| 12 - | - | - | - | - | - | - | - | - | - | - | - | +| 13 - | - | - | - | - | - | - | - | - | - | - | - | +| 14 MISO | 14 | 12 | MISO | - | - | - | - | P2-6* | - | - | - | +| 15 SCLK | 15 | 14 | SCLK | - | - | - | - | P2-9* | - | - | - | +| 16 MOSI | 16 | 13 | MOSI | - | - | - | - | - | - | - | - | +| 17 - | - | - | - | - | - | - | - | - | - | - | - | +| 18 Analog | 18 | 27 | - | - | - | - | - | P2-1 | - | P2-7 | - | +| 19 Analog | 19 | 26 | - | - | - | - | - | P2-2 | - | P2-8 | - | +| 20 Analog | 20 | 25 | - | - | - | - | - | P2-3 | - | P2-2 | - | +| 21 Analog | 21 | 33 | - | - | - | - | - | P2-4 | - | P2-3 | - | +| 22 - | - | - | - | - | - | - | - | - | - | - | SENSE | +| 23 3.3V VCC | - | 3.3V VCC | 3.3V VCC | - | - | 3.3V VCC | 3.3V VCC | - | - | - | 3.3V VCC | +| 24 5V VCC | 5V VCC OUT | 5V VCC | 5V VCC | 5V VCC | 5V VCC | - | 5V VCC | PX-5 5V VCC | 5V VCC | PX-1 5V VCC | - | +| 25 GND | GND | GND | GND | GND | - | GND | GND | PX-8 GND | GND | PX-9 GND | GND | * 2nd player Genesis is incompatible with Radio because it uses the same pins, 1 player Genesis is compatible + Ω This is optional and only used for dongle detection. On the microcontroller side, put a 1k resistor between DB-25 pin 9 and VCC (3.3v for ESP32, 5V for Micro). On each controller dongle, put a resistor of the given value between DB-25 pin 9 and GND. All connected pins can also function as Digital pins. diff --git a/src/WiiExtension.cpp b/src/WiiExtension.cpp new file mode 100644 index 0000000..a57a5da --- /dev/null +++ b/src/WiiExtension.cpp @@ -0,0 +1,170 @@ +/* +Wii Nunchuck/Wii Classic/SNES+NES Classic: + LOOKING AT THE PLUG ON FRONT OF CONSOLE/BACK OF WIIMOTE (not coming from controller) + + |---------------| + | 1 3 5 | + | o o o | + | o o o | + | 2 4 6 | + | |-------| | + |---| |---| + + PIN # USAGE (colors from my extension cable, check your own) + + 1: VCC 3.3V ONLY - white + 2: SCL - yellow + 3: 3.3V SENSE, unused - red + 4: unused - + 5: SDA - green + 6: GND - black +*/ + +#include + +// we only support 1 pad here +#define GAMEPAD_COUNT 1 + +#define AXIS_CENTER_IN 126 +#define AXIS_MAX_IN 230 +#define AXIS_MIN_IN 15 + +#define TRIGGER_MAX_IN 255 +#define TRIGGER_MIN_IN 40 + +#include + +#include "gamepad/Gamepad.h" +#include "util.cpp" + +GAMEPAD_CLASS gamepad; + +ExtensionPort port; // Port for communicating with extension controllers + +Nunchuk::Shared nchuk(port); // Read Nunchuk formatted data from the port +ClassicController::Shared classic(port); // Read Classic Controller formatted data from the port + +ExtensionController* controllers[] = { + // Array of available controllers, for controller-specific init + &nchuk, + &classic, +}; + +const int NumControllers = sizeof(controllers) / sizeof(ExtensionController*); // # of controllers, auto-generated + +void (*controllerChanged)(); + +const uint8_t c = 0; // for now just do 1 pad + +void nunchuckChanged() { + //nchuk.printDebug(); return; + gamepad.buttons(c, 0); + if (nchuk.buttonC()) { + gamepad.press(c, BUTTON_A); + } + if (nchuk.buttonZ()) { + gamepad.press(c, BUTTON_B); + } + // todo: anything with roll/pitch/accel ? + gamepad.setAxis(c, translateAxis(nchuk.joyX()), -translateAxis(nchuk.joyY()), 0, 0, 0, 0, DPAD_CENTER); +} + +void classicChanged() { + //classic.printDebug(); return; + gamepad.buttons(c, 0); + if (classic.buttonA()) { + gamepad.press(c, BUTTON_A); + } + if (classic.buttonB()) { + gamepad.press(c, BUTTON_B); + } + if (classic.buttonY()) { + gamepad.press(c, BUTTON_Y); + } + if (classic.buttonX()) { + gamepad.press(c, BUTTON_X); + } + if (classic.buttonZL()) { + gamepad.press(c, BUTTON_L); + } + if (classic.buttonZR()) { + gamepad.press(c, BUTTON_R); + } + if (classic.buttonL()) { + gamepad.press(c, BUTTON_TL2); + } + if (classic.buttonR()) { + gamepad.press(c, BUTTON_TR2); + } + if (classic.buttonPlus()) { + gamepad.press(c, BUTTON_PLUS); + } + if (classic.buttonMinus()) { + gamepad.press(c, BUTTON_MINUS); + } + if (classic.buttonHome()) { + gamepad.press(c, BUTTON_HOME); + } + auto hat = calculateDpadDirection(classic.dpadUp(), classic.dpadDown(), classic.dpadLeft(), classic.dpadRight()); + gamepad.setAxis(c, + translateAxis(classic.leftJoyX()), + -translateAxis(classic.leftJoyY()), + translateAxis(classic.rightJoyX()), + -translateAxis(classic.rightJoyY()), + translateTrigger(classic.triggerL()), + translateTrigger(classic.triggerR()), + hat); +} + +boolean connectController() { + boolean connected = port.connect(); // Connect to the controller + + if (connected == true) { + for (int i = 0; i < NumControllers; i++) { + if (controllers[i]->controllerTypeMatches()) { // If this controller is connected... + connected = controllers[i]->specificInit(); // ...run the controller-specific initialization + if (connected == true) { + ExtensionType conType = port.getControllerType(); + switch (conType) { + case (ExtensionType::Nunchuk): + controllerChanged = nunchuckChanged; + break; + case (ExtensionType::ClassicController): + controllerChanged = classicChanged; + break; + default: + //Serial.println("Other controller connected!"); + return false; + } + return true; + } + } + } + } + + return connected; +} + +void setup() { + gamepad.begin(); + port.begin(); // init I2C + + while (!connectController()) { + //Serial.println("No controller found!"); + delay(1000); + } +} + +void loop() { + boolean success = port.update(); // Get new data from the controller + + if (success == true) { // We've got data! + // todo: only call this if data changed? + controllerChanged(); + } else { // Data is bad :( + while (!connectController()) { + //Serial.println("Controller Disconnected!"); + delay(1000); + } + } +} diff --git a/src/gamepad/common.h b/src/gamepad/common.h index faed89b..571174c 100644 --- a/src/gamepad/common.h +++ b/src/gamepad/common.h @@ -78,6 +78,8 @@ // aliases #define BUTTON_HOME BUTTON_MENU +#define BUTTON_MINUS BUTTON_SELECT +#define BUTTON_PLUS BUTTON_START #define BUTTON_L BUTTON_TL #define BUTTON_L1 BUTTON_TL #define BUTTON_R BUTTON_TR