Skip to content

Commit

Permalink
Wii addon refactor and button/analog mapping support (OpenStickCommun…
Browse files Browse the repository at this point in the history
…ity#501)

* Added improved Wii extension detection.
Added GHWT touch fret support.
Added initial Wii extension hot plugging support.
Fixed issue with detecting GHWT guitars.
Fixed issue with guitar analog values.

* Refactor of WiiExtension library to better separate controller contexts.

* Added analog calibration. If controller does not have stored calibration, default is used (implemented per-controller). Verifies calibration checksum to determine which is used.

* Adjust default analog calibration when data is unavailable on the device. Fixed issue where adjusted input values would overflow after calibration.

* Added default calibration for Drums and Turntable extensions since no calibration exists on device. Implemented default button mapping config in prep for web-config mapping options.

* Moved WiiExtensionController enum to a type.

* Added toggle state for DJ Hero Euphoria button LED.

* Refactored polling logic to allow for options on boot

* Refactor of Wii addon to include button and analog mapping.
Included separation of Wii addon-specific L10n strings to Locales/en/Addons/WiiAddon.jsx

* Fixed issue causing Classic Pro-based controllers from functioning.
Updated documentation to remove Wii controller mapping details and add new image.

* Fixes unintentional tabs and moved unneeded debug variables behind WII_EXTENSION_DEBUG

* Minor view refactors on input selectors

* Fixed key warnings
  • Loading branch information
mikepparks authored Sep 9, 2023
1 parent 610ce65 commit dca1fdd
Show file tree
Hide file tree
Showing 32 changed files with 2,716 additions and 886 deletions.
Binary file modified docs/assets/images/gpc-add-ons-wii-extensions.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 3 additions & 19 deletions docs/web-configurator-add-ons.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,28 +163,12 @@ Enabling this add-on will allow you to use GP2040-CE on a PS4 with an 8 minute t
* `I2C Block` - The block of I2C to use (i2c0 or i2c1).
* `I2C Speed` - Sets the speed of I2C communication. Common values are `100000` for standard, or `400000` for fast.

Supported Extension Controllers and their mapping is as follows:

| GP2040-CE | Nunchuck | Classic | Guitar Hero Guitar |
|-----------|----------|--------------|--------------------|
| B1 | C | B | Green |
| B2 | Z | A | Red |
| B3 | | Y | Blue |
| B4 | | X | Yellow |
| L1 | | L | |
| L2 | | ZL | |
| R1 | | R | |
| R2 | | ZR | |
| S1 | | Select | |
| S2 | | Start | |
| A1 | | Home | |
| D-Pad | | D-Pad | Strum Up/Down |
| Analog | Left | Left & Right | Left |

Classic Controller support includes Classic, Classic Pro, and NES/SNES Mini Controllers.
Classic Controller support includes Classic, Classic Pro, and NES/SNES Mini Controllers.

Original Classic Controller L & R triggers are analog sensitive, where Pro triggers are not.

Due to an accessory hardware issue, Drum & DJ turntable controllers may require hot-swapping from a Nunchuk or Classic controller before being usable.

## SNES Input

![GP2040-CE Configurator - SNES Input](assets/images/gpc-add-ons-snespad-input.png)
Expand Down
278 changes: 273 additions & 5 deletions headers/addons/wiiext.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
#define _WIIExtensionAddon_H

#include <string>
#include <map>
#include <vector>
#include <numeric>
#include <stdint.h>
#include <hardware/i2c.h>
#include "BoardConfig.h"
Expand Down Expand Up @@ -37,18 +40,241 @@
#define WII_EXTENSION_I2C_SPEED 400000
#endif

#define WII_SET_MASK(bits, check, val) ((check) ? ((bits) |= (val)) : ((bits) &= ~(val)))

typedef enum {
WII_ANALOG_TYPE_NONE,
WII_ANALOG_TYPE_LEFT_STICK_X,
WII_ANALOG_TYPE_LEFT_STICK_Y,
WII_ANALOG_TYPE_RIGHT_STICK_X,
WII_ANALOG_TYPE_RIGHT_STICK_Y,
WII_ANALOG_TYPE_DPAD_X,
WII_ANALOG_TYPE_DPAD_Y,
WII_ANALOG_TYPE_LEFT_TRIGGER,
WII_ANALOG_TYPE_RIGHT_TRIGGER,
WII_ANALOG_TYPE_LEFT_STICK_X_PLUS,
WII_ANALOG_TYPE_LEFT_STICK_X_MINUS,
WII_ANALOG_TYPE_LEFT_STICK_Y_PLUS,
WII_ANALOG_TYPE_LEFT_STICK_Y_MINUS,
WII_ANALOG_TYPE_RIGHT_STICK_X_PLUS,
WII_ANALOG_TYPE_RIGHT_STICK_X_MINUS,
WII_ANALOG_TYPE_RIGHT_STICK_Y_PLUS,
WII_ANALOG_TYPE_RIGHT_STICK_Y_MINUS,
WII_ANALOG_TYPE_COUNT
} WiiAnalogType;

typedef struct {
uint16_t axisType;
uint16_t minRange;
uint16_t maxRange;
} WiiAnalogAxis;

typedef struct {
// button ID = gamepad mask value
std::unordered_map<uint16_t, uint32_t> buttonMap;
std::unordered_map<uint16_t, WiiAnalogAxis> analogMap;
} WiiExtensionConfig;

typedef struct {
uint16_t analogInput;
uint16_t analogValue;
} WiiAnalogChange;

class WiiExtensionInput : public GPAddon {
public:
virtual bool available();
virtual void setup(); // WiiExtension Setup
virtual void process(); // WiiExtension Process
virtual void preprocess() {}
virtual std::string name() { return WiiExtensionName; }
virtual bool available();
virtual void setup(); // WiiExtension Setup
virtual void process(); // WiiExtension Process
virtual void preprocess() {}
virtual std::string name() { return WiiExtensionName; }
private:
WiiExtension * wii;
uint32_t uIntervalMS;
uint32_t nextTimer;

// controller ID = config
// defaults if no defined config
std::unordered_map<uint16_t, WiiExtensionConfig> extensionConfigs = {
{
WiiExtensionController::WII_EXTENSION_NUNCHUCK,
{
{
{WiiButtons::WII_BUTTON_C,GAMEPAD_MASK_B1},
{WiiButtons::WII_BUTTON_Z,GAMEPAD_MASK_B2},
},
{
{
WiiAnalogs::WII_ANALOG_LEFT_X,
{ WiiAnalogType::WII_ANALOG_TYPE_LEFT_STICK_X, 0, 0 }
},
{
WiiAnalogs::WII_ANALOG_LEFT_Y,
{ WiiAnalogType::WII_ANALOG_TYPE_LEFT_STICK_Y, 0, 0 }
},
}
}
},
{
WiiExtensionController::WII_EXTENSION_CLASSIC,
{
{
{WiiButtons::WII_BUTTON_B, GAMEPAD_MASK_B1},
{WiiButtons::WII_BUTTON_A, GAMEPAD_MASK_B2},
{WiiButtons::WII_BUTTON_X, GAMEPAD_MASK_B4},
{WiiButtons::WII_BUTTON_Y, GAMEPAD_MASK_B3},
{WiiButtons::WII_BUTTON_L, GAMEPAD_MASK_L2},
{WiiButtons::WII_BUTTON_ZL, GAMEPAD_MASK_L1},
{WiiButtons::WII_BUTTON_R, GAMEPAD_MASK_R2},
{WiiButtons::WII_BUTTON_ZR, GAMEPAD_MASK_R1},
{WiiButtons::WII_BUTTON_MINUS, GAMEPAD_MASK_S1},
{WiiButtons::WII_BUTTON_PLUS, GAMEPAD_MASK_S2},
{WiiButtons::WII_BUTTON_HOME, GAMEPAD_MASK_A1},
{WiiButtons::WII_BUTTON_UP, GAMEPAD_MASK_DU},
{WiiButtons::WII_BUTTON_DOWN, GAMEPAD_MASK_DD},
{WiiButtons::WII_BUTTON_LEFT, GAMEPAD_MASK_DL},
{WiiButtons::WII_BUTTON_RIGHT, GAMEPAD_MASK_DR},
},
{
{
WiiAnalogs::WII_ANALOG_LEFT_X,
{ WiiAnalogType::WII_ANALOG_TYPE_LEFT_STICK_X, 0, 0 }
},
{
WiiAnalogs::WII_ANALOG_LEFT_Y,
{ WiiAnalogType::WII_ANALOG_TYPE_LEFT_STICK_Y, 0, 0 }
},
{
WiiAnalogs::WII_ANALOG_RIGHT_X,
{ WiiAnalogType::WII_ANALOG_TYPE_RIGHT_STICK_X, 0, 0 }
},
{
WiiAnalogs::WII_ANALOG_RIGHT_Y,
{ WiiAnalogType::WII_ANALOG_TYPE_RIGHT_STICK_Y, 0, 0 }
},
{
WiiAnalogs::WII_ANALOG_LEFT_TRIGGER,
{ WiiAnalogType::WII_ANALOG_TYPE_LEFT_TRIGGER, 0, 0 }
},
{
WiiAnalogs::WII_ANALOG_RIGHT_TRIGGER,
{ WiiAnalogType::WII_ANALOG_TYPE_RIGHT_TRIGGER, 0, 0 }
},
}
}
},
{
WiiExtensionController::WII_EXTENSION_TAIKO,
{
{
{TaikoButtons::TATA_KAT_LEFT, GAMEPAD_MASK_L2},
{TaikoButtons::TATA_KAT_RIGHT, GAMEPAD_MASK_R2},
{TaikoButtons::TATA_DON_RIGHT, GAMEPAD_MASK_B1},
{TaikoButtons::TATA_DON_LEFT, GAMEPAD_MASK_DL},
},
{}
}
},
{
WiiExtensionController::WII_EXTENSION_GUITAR,
{
{
{GuitarButtons::GUITAR_RED, GAMEPAD_MASK_B2},
{GuitarButtons::GUITAR_GREEN, GAMEPAD_MASK_B1},
{GuitarButtons::GUITAR_YELLOW, GAMEPAD_MASK_B4},
{GuitarButtons::GUITAR_BLUE, GAMEPAD_MASK_B3},
{GuitarButtons::GUITAR_ORANGE, GAMEPAD_MASK_L2},
{GuitarButtons::GUITAR_PEDAL, GAMEPAD_MASK_R2},
{WiiButtons::WII_BUTTON_MINUS, GAMEPAD_MASK_S1},
{WiiButtons::WII_BUTTON_PLUS, GAMEPAD_MASK_S2},
{WiiButtons::WII_BUTTON_UP, GAMEPAD_MASK_DU},
{WiiButtons::WII_BUTTON_DOWN, GAMEPAD_MASK_DD},
},
{
{
WiiAnalogs::WII_ANALOG_LEFT_X,
{ WiiAnalogType::WII_ANALOG_TYPE_LEFT_STICK_X, 0, 0 }
},
{
WiiAnalogs::WII_ANALOG_LEFT_Y,
{ WiiAnalogType::WII_ANALOG_TYPE_LEFT_STICK_Y, 0, 0 }
},
{
WiiAnalogs::WII_ANALOG_RIGHT_X,
{ WiiAnalogType::WII_ANALOG_TYPE_RIGHT_STICK_X, 0, 0 }
},
}
}
},
{
WiiExtensionController::WII_EXTENSION_DRUMS,
{
{
{DrumButtons::DRUM_RED, GAMEPAD_MASK_B2},
{DrumButtons::DRUM_GREEN, GAMEPAD_MASK_B1},
{DrumButtons::DRUM_BLUE, GAMEPAD_MASK_B4},
{DrumButtons::DRUM_YELLOW, GAMEPAD_MASK_B3},
{DrumButtons::DRUM_ORANGE, GAMEPAD_MASK_L2},
{DrumButtons::DRUM_PEDAL, GAMEPAD_MASK_R2},
{WiiButtons::WII_BUTTON_MINUS, GAMEPAD_MASK_S1},
{WiiButtons::WII_BUTTON_PLUS, GAMEPAD_MASK_S2},
},
{
{
WiiAnalogs::WII_ANALOG_LEFT_X,
{ WiiAnalogType::WII_ANALOG_TYPE_LEFT_STICK_X, 0, 0 }
},
{
WiiAnalogs::WII_ANALOG_LEFT_Y,
{ WiiAnalogType::WII_ANALOG_TYPE_LEFT_STICK_Y, 0, 0 }
},
}
}
},
{
WiiExtensionController::WII_EXTENSION_TURNTABLE,
{
{
{TurntableButtons::TURNTABLE_RIGHT_GREEN, GAMEPAD_MASK_B3},
{TurntableButtons::TURNTABLE_RIGHT_RED, GAMEPAD_MASK_B4},
{TurntableButtons::TURNTABLE_RIGHT_BLUE, GAMEPAD_MASK_B2},
{TurntableButtons::TURNTABLE_EUPHORIA, GAMEPAD_MASK_R1},
{TurntableButtons::TURNTABLE_LEFT_GREEN, GAMEPAD_MASK_DL},
{TurntableButtons::TURNTABLE_LEFT_RED, GAMEPAD_MASK_DU},
{TurntableButtons::TURNTABLE_LEFT_BLUE, GAMEPAD_MASK_DR},
{WiiButtons::WII_BUTTON_MINUS, GAMEPAD_MASK_S1},
{WiiButtons::WII_BUTTON_PLUS, GAMEPAD_MASK_S2},
},
{
{
WiiAnalogs::WII_ANALOG_LEFT_X,
{ WiiAnalogType::WII_ANALOG_TYPE_LEFT_STICK_X, 0, 0 }
},
{
WiiAnalogs::WII_ANALOG_LEFT_Y,
{ WiiAnalogType::WII_ANALOG_TYPE_LEFT_STICK_Y, 0, 0 }
},
{
WiiAnalogs::WII_ANALOG_RIGHT_X,
{ WiiAnalogType::WII_ANALOG_TYPE_RIGHT_STICK_X, 0, 0 }
},
{
WiiAnalogs::WII_ANALOG_RIGHT_Y,
{ WiiAnalogType::WII_ANALOG_TYPE_RIGHT_STICK_Y, 0, 0 }
},
{
WiiAnalogs::WII_ANALOG_LEFT_TRIGGER,
{ WiiAnalogType::WII_ANALOG_TYPE_RIGHT_STICK_X, 0, 0 }
},
{
WiiAnalogs::WII_ANALOG_RIGHT_TRIGGER,
{ WiiAnalogType::WII_ANALOG_TYPE_RIGHT_STICK_X, 0, 0 }
},
}
}
},
};
WiiExtensionConfig* currentConfig = NULL;

bool buttonC = false;
bool buttonZ = false;

Expand All @@ -72,14 +298,56 @@ class WiiExtensionInput : public GPAddon {

uint16_t triggerLeft = 0;
uint16_t triggerRight = 0;
uint16_t lastTriggerLeft = 0;
uint16_t lastTriggerRight = 0;
uint16_t whammyBar = 0;

uint16_t leftX = 0;
uint16_t lastLeftX = 0;

uint16_t leftY = 0;
uint16_t lastLeftY = 0;

uint16_t rightX = 0;
uint16_t lastRightX = 0;

uint16_t rightY = 0;
uint16_t lastRightY = 0;

std::map<uint16_t, std::vector<WiiAnalogChange>> analogChanges = {
{WII_ANALOG_TYPE_LEFT_STICK_X,{}},
{WII_ANALOG_TYPE_LEFT_STICK_Y,{}},
{WII_ANALOG_TYPE_RIGHT_STICK_X,{}},
{WII_ANALOG_TYPE_RIGHT_STICK_Y,{}},
{WII_ANALOG_TYPE_DPAD_X,{}},
{WII_ANALOG_TYPE_DPAD_Y,{}},
{WII_ANALOG_TYPE_LEFT_TRIGGER,{}},
{WII_ANALOG_TYPE_RIGHT_TRIGGER,{}},

{WII_ANALOG_TYPE_LEFT_STICK_X_PLUS,{}},
{WII_ANALOG_TYPE_LEFT_STICK_X_MINUS,{}},
{WII_ANALOG_TYPE_LEFT_STICK_Y_PLUS,{}},
{WII_ANALOG_TYPE_LEFT_STICK_Y_MINUS,{}},
{WII_ANALOG_TYPE_RIGHT_STICK_X_PLUS,{}},
{WII_ANALOG_TYPE_RIGHT_STICK_X_MINUS,{}},
{WII_ANALOG_TYPE_RIGHT_STICK_Y_PLUS,{}},
{WII_ANALOG_TYPE_RIGHT_STICK_Y_MINUS,{}},
};

uint16_t map(uint16_t x, uint16_t in_min, uint16_t in_max, uint16_t out_min, uint16_t out_max);
uint16_t bounds(uint16_t x, uint16_t out_min, uint16_t out_max);

void update();
void setControllerButton(uint16_t controllerID, uint16_t buttonID, uint32_t buttonMask);
void setControllerAnalog(uint16_t controllerID, uint16_t analogID, uint32_t axisType);
void setControllerStickMode(uint16_t controllerID, uint16_t analogID, uint32_t axisType);
void setButtonState(bool buttonState, uint16_t buttonMask);
void queueAnalogChange(uint16_t analogInput, uint16_t analogValue, uint16_t lastAnalogValue);
void updateAnalogState();
void reloadConfig();

uint16_t getAverage(std::vector<WiiAnalogChange> const& changes);
uint16_t getDelta(std::vector<uint16_t> const& changes, uint16_t baseValue);
};

#endif // _WIIExtensionAddon_H
4 changes: 4 additions & 0 deletions headers/gamepad/GamepadState.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@
#define GAMEPAD_JOYSTICK_MID 0x7FFF
#define GAMEPAD_JOYSTICK_MAX 0xFFFF

#define GAMEPAD_TRIGGER_MIN 0
#define GAMEPAD_TRIGGER_MID 0x7F
#define GAMEPAD_TRIGGER_MAX 0xFF

/**
* @brief AUX defines --- gamepad state that doesn't translate to an output button/dpad/etc.
*/
Expand Down
17 changes: 12 additions & 5 deletions lib/WiiExtension/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
add_library(WiiExtension WiiExtension.cpp)
target_link_libraries(WiiExtension PUBLIC BitBang_I2C)
target_include_directories(WiiExtension INTERFACE .)
target_include_directories(WiiExtension PUBLIC
BitBang_I2C
add_library(WiiExtension
WiiExtension.cpp
extensions/ExtensionBase.cpp
extensions/ClassicExtension.cpp
extensions/DrumExtension.cpp
extensions/GuitarExtension.cpp
extensions/NunchuckExtension.cpp
extensions/TaikoExtension.cpp
extensions/TurntableExtension.cpp
)
target_link_libraries(WiiExtension PUBLIC pico_stdlib hardware_i2c)
target_include_directories(WiiExtension INTERFACE .)
target_include_directories(WiiExtension PUBLIC .)
1 change: 0 additions & 1 deletion lib/WiiExtension/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# WiiExtension
# Ported to BitBangI2C
#
# Written by:
# Mike Parks
Expand Down
Loading

0 comments on commit dca1fdd

Please sign in to comment.