Browse Source

Add Nintendo Wii Nunchuck/Wii Classic/SNES+NES Mini support

master
Travis Burtrum 5 months ago
parent
commit
ff5273b844
4 changed files with 248 additions and 36 deletions
  1. +46
    -7
      platformio.ini
  2. +30
    -29
      readme.md
  3. +170
    -0
      src/WiiExtension.cpp
  4. +2
    -0
      src/gamepad/common.h

+ 46
- 7
platformio.ini View File

@ -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 = -<*> +<WiiExtension.cpp>
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]


+ 30
- 29
readme.md View File

@ -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.


+ 170
- 0
src/WiiExtension.cpp View File

@ -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 <Arduino.h>
// 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 <NintendoExtensionCtrl.h>
#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);
}
}
}

+ 2
- 0
src/gamepad/common.h View File

@ -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


Loading…
Cancel
Save