Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions headers/addons/wiiext.h
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@ class WiiExtensionInput : public GPAddon {
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);
bool getButtonState(uint16_t buttonMask);
void queueAnalogChange(uint16_t analogInput, uint16_t analogValue, uint16_t lastAnalogValue);
void updateAnalogState();
void updateMotionState();
Expand Down
5 changes: 3 additions & 2 deletions lib/WiiExtension/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ add_library(WiiExtension
extensions/MotionPlusExtension.cpp
extensions/NunchuckExtension.cpp
extensions/TaikoExtension.cpp
extensions/TrainExtension.cpp
extensions/TurntableExtension.cpp
extensions/UDrawExtension.cpp
)
target_link_libraries(WiiExtension PUBLIC pico_stdlib PicoPeripherals CRC32)
target_link_libraries(WiiExtension PUBLIC pico_stdlib pico_i2c_slave PicoPeripherals CRC32)
target_include_directories(WiiExtension INTERFACE .)
target_include_directories(WiiExtension PUBLIC . PicoPeripherals CRC32)
target_include_directories(WiiExtension PUBLIC . pico_i2c_slave PicoPeripherals CRC32)
11 changes: 7 additions & 4 deletions lib/WiiExtension/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# WiiExtension
#
# Written by:
# Mike Parks
# <mikepparks@gmail.com>

Wii extension controller input/output handling for pico-sdk based projects via I2C.

Written by:
Mike Parks @mikepparks

Output encryption functionality based on work by @Santroller, @RobertDaleSmith, and marcan.
932 changes: 748 additions & 184 deletions lib/WiiExtension/WiiExtension.cpp

Large diffs are not rendered by default.

88 changes: 54 additions & 34 deletions lib/WiiExtension/WiiExtension.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "pico/stdlib.h"
#include "hardware/i2c.h"
#include "pico/i2c_slave.h"
#include "peripheral_i2c.h"

#include "extensions/Extensions.h"
Expand Down Expand Up @@ -99,6 +100,7 @@ typedef enum {
#define WII_CHECKSUM_MAGIC 0x55
#define WII_CALIBRATION_SIZE 0x10
#define WII_CALIBRATION_CHECKSUM_SIZE 0x02
#define WII_EXT_MEMORY_SIZE 256

static volatile bool WiiExtension_alarmFired;

Expand All @@ -116,47 +118,65 @@ static volatile bool WiiExtension_alarmFired;
#define TOUCH_BETWEEN_RANGE(val,beg,end) (((val) >= ((beg)-WII_GUITAR_TOUCHPAD_OVERLAP)) && ((val) < (end)))
#define WII_DECRYPT_BYTE(x) (((x) ^ 0x17) + 0x17)

class WiiExtension {
protected:
uint8_t address;
PeripheralI2C* i2c;
public:
int8_t extensionType = WII_EXTENSION_NONE;
int8_t dataType = WII_DATA_TYPE_0;

bool isReady = false;

// Constructor
WiiExtension() {}
WiiExtension(PeripheralI2C *i2cController, uint8_t addr);

// Methods
void begin();
void reset();
void start();
void poll();
static bool WiiExtension_isCryptoEnabled;
static uint8_t WiiExtension_extensionMemory[WII_EXT_MEMORY_SIZE];
static uint16_t WiiExtension_memoryCursor;
static bool WiiExtension_hasAddress;
static bool WiiExtension_firstRead;
static uint8_t WiiExtension_ft[8];
static uint8_t WiiExtension_sb[8];

void setI2C(PeripheralI2C *i2cController) { this->i2c = i2cController; }
void setAddress(uint8_t addr) { this->address = addr; }

ExtensionBase* getController() { return extensionController; };
private:
ExtensionBase *extensionController = NULL;
class WiiExtension {
protected:
uint8_t address;
PeripheralI2C* i2c;
public:
int8_t extensionType = WII_EXTENSION_NONE;
int8_t dataType = WII_DATA_TYPE_0;

// false = read input from connected device (default)
// true = output as extension
bool extensionMode = false;

bool isReady = false;

// Constructor
WiiExtension() {}
WiiExtension(PeripheralI2C *i2cController, uint8_t addr);

// Methods
void begin();
void reset();
void start();
void poll();

void setI2C(PeripheralI2C *i2cController) { this->i2c = i2cController; }
void setAddress(uint8_t addr) { this->address = addr; }
void setExtensionMode(bool extMode) { this->extensionMode = extMode; }

ExtensionBase* getController() { return extensionController; };
private:
ExtensionBase *extensionController = NULL;

#if WII_EXTENSION_DEBUG==true
uint8_t _lastRead[16] = {0xFF};
uint8_t _lastRead[16] = {0xFF};
#endif

int doI2CWrite(uint8_t *pData, int iLen);
int doI2CRead(uint8_t *pData, int iLen);
uint8_t doI2CTest();
void doI2CInit();
int doI2CWrite(uint8_t *pData, int iLen);
int doI2CRead(uint8_t *pData, int iLen);
uint8_t doI2CTest();
void doI2CInit();

void waitUntil_us(uint64_t us);
static void alarmIRQ();

void waitUntil_us(uint64_t us);
static void alarmIRQ();
bool isMotionPlus = false;
bool isExtension = false;

bool isMotionPlus = false;
bool isExtension = false;
static void i2cHandler(i2c_inst_t *i2c, i2c_slave_event_t event);
static void initCrypt(const uint8_t key[16]);
static void decrypt(uint8_t* data, uint8_t addr, uint8_t len);
static void encrypt(uint8_t* data, uint8_t addr, uint8_t len);
};

#endif
111 changes: 110 additions & 1 deletion lib/WiiExtension/extensions/ClassicExtension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,4 +207,113 @@ void ClassicExtension::process(uint8_t *inputData) {
//printf("Joy1 X=%5d Y=%5d Joy2 X=%5d Y=%5d U=%1d D=%1d L=%1d R=%1d TL=%5d TR=%5d\n", analogState[WiiAnalogs::ANALOG_LEFT_X], analogState[WiiAnalogs::ANALOG_LEFT_Y], analogState[WiiAnalogs::ANALOG_RIGHT_X], analogState[WiiAnalogs::ANALOG_RIGHT_Y], directionalPad[WiiDirectionalPad::DIRECTION_UP], directionalPad[WiiDirectionalPad::DIRECTION_DOWN], directionalPad[WiiDirectionalPad::DIRECTION_LEFT], directionalPad[WiiDirectionalPad::DIRECTION_RIGHT], analogState[WiiAnalogs::ANALOG_TRIGGER_LEFT], analogState[WiiAnalogs::ANALOG_TRIGGER_RIGHT]);
//printf("A=%1d B=%1d X=%1d Y=%1d ZL=%1d ZR=%1d LT=%1d RT=%1d -=%1d H=%1d +=%1d\n", buttonA, buttonB, buttonX, buttonY, buttonZL, buttonZR, buttonLT, buttonRT, buttonMinus, buttonHome, buttonPlus);
#endif
}
}

uint8_t ClassicExtension::prepareOutput() {
uint16_t lx = 0;
uint16_t ly = 0;
uint16_t rx = 0;
uint16_t ry = 0;
uint16_t lt = 0;
uint16_t rt = 0;
// expect all source analog sticks at 16 bit and scale down
// expect all source analog triggers at 8 bit and scale down
if (getDataType() == WII_DATA_TYPE_1) {
lx = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_LEFT_X] * 0x3F) / 0xFFFF);
ly = (uint8_t)(0x3F - ((analogState[WiiAnalogs::WII_ANALOG_LEFT_Y] * 0x3F) / 0xFFFF));
rx = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_RIGHT_X] * 0x1F) / 0xFFFF);
ry = (uint8_t)(0x1F - ((analogState[WiiAnalogs::WII_ANALOG_RIGHT_Y] * 0x1F) / 0xFFFF));
lt = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_LEFT_TRIGGER] * 0x1F) / 0xFF);
rt = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_RIGHT_TRIGGER] * 0x1F) / 0xFF);

controllerData[0x00] = ((rx & 0x18) << 3) | (lx & 0x3F);
controllerData[0x01] = ((rx & 0x06) << 5) | (ly & 0x3F);
controllerData[0x02] = ((rx & 0x01) << 7) | ((lt & 0x0C) << 5) | (ry & 0x1F);
controllerData[0x03] = ((lt & 0x07) << 5) | (rt & 0x0F);
controllerData[0x04] = (1 |
((!(buttons[WiiButtons::WII_BUTTON_R] & 0x01) << 1)) |
((!(buttons[WiiButtons::WII_BUTTON_PLUS] & 0x01) << 2)) |
((!(buttons[WiiButtons::WII_BUTTON_HOME] & 0x01) << 3)) |
((!(buttons[WiiButtons::WII_BUTTON_MINUS] & 0x01) << 4)) |
((!(buttons[WiiButtons::WII_BUTTON_L] & 0x01) << 5)) |
((!(buttons[WiiButtons::WII_BUTTON_DOWN] & 0x01) << 6)) |
((!(buttons[WiiButtons::WII_BUTTON_RIGHT] & 0x01) << 7))
);
controllerData[0x05] = (
((!(buttons[WiiButtons::WII_BUTTON_UP] & 0x01)) << 0) |
((!(buttons[WiiButtons::WII_BUTTON_LEFT] & 0x01)) << 1) |
((!(buttons[WiiButtons::WII_BUTTON_ZR] & 0x01)) << 2) |
((!(buttons[WiiButtons::WII_BUTTON_X] & 0x01)) << 3) |
((!(buttons[WiiButtons::WII_BUTTON_A] & 0x01)) << 4) |
((!(buttons[WiiButtons::WII_BUTTON_Y] & 0x01)) << 5) |
((!(buttons[WiiButtons::WII_BUTTON_B] & 0x01)) << 6) |
((!(buttons[WiiButtons::WII_BUTTON_ZL] & 0x01)) << 7)
);
return 6;
} else if (getDataType() == WII_DATA_TYPE_2) {
lx = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_LEFT_X] * 0x3FF) / 0xFFFF);
ly = (uint8_t)(0x3F - ((analogState[WiiAnalogs::WII_ANALOG_LEFT_Y] * 0x3FF) / 0xFFFF));
rx = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_RIGHT_X] * 0x3FF) / 0xFFFF);
ry = (uint8_t)(0x1F - ((analogState[WiiAnalogs::WII_ANALOG_RIGHT_Y] * 0x3FF) / 0xFFFF));
lt = analogState[WiiAnalogs::WII_ANALOG_LEFT_TRIGGER];
rt = analogState[WiiAnalogs::WII_ANALOG_RIGHT_TRIGGER];

controllerData[0x00] = ((lx & 0x03FC) >> 2);
controllerData[0x01] = ((rx & 0x03FC) >> 2);
controllerData[0x02] = ((ly & 0x03FC) >> 2);
controllerData[0x03] = ((ry & 0x03FC) >> 2);
controllerData[0x04] = ((lx & 0x03) << 0) | ((rx & 0x03) << 2) | ((ly & 0x03) << 4) | ((ry & 0x03) << 6);
controllerData[0x05] = lt;
controllerData[0x06] = rt;
controllerData[0x07] = (1 |
((!(buttons[WiiButtons::WII_BUTTON_R] & 0x01) << 1)) |
((!(buttons[WiiButtons::WII_BUTTON_PLUS] & 0x01) << 2)) |
((!(buttons[WiiButtons::WII_BUTTON_HOME] & 0x01) << 3)) |
((!(buttons[WiiButtons::WII_BUTTON_MINUS] & 0x01) << 4)) |
((!(buttons[WiiButtons::WII_BUTTON_L] & 0x01) << 5)) |
((!(buttons[WiiButtons::WII_BUTTON_DOWN] & 0x01) << 6)) |
((!(buttons[WiiButtons::WII_BUTTON_RIGHT] & 0x01) << 7))
);
controllerData[0x08] = (
((!(buttons[WiiButtons::WII_BUTTON_UP] & 0x01)) << 0) |
((!(buttons[WiiButtons::WII_BUTTON_LEFT] & 0x01)) << 1) |
((!(buttons[WiiButtons::WII_BUTTON_ZR] & 0x01)) << 2) |
((!(buttons[WiiButtons::WII_BUTTON_X] & 0x01)) << 3) |
((!(buttons[WiiButtons::WII_BUTTON_A] & 0x01)) << 4) |
((!(buttons[WiiButtons::WII_BUTTON_Y] & 0x01)) << 5) |
((!(buttons[WiiButtons::WII_BUTTON_B] & 0x01)) << 6) |
((!(buttons[WiiButtons::WII_BUTTON_ZL] & 0x01)) << 7)
);
return 9;
} else if (getDataType() == WII_DATA_TYPE_3) {
controllerData[0x00] = analogState[WiiAnalogs::WII_ANALOG_LEFT_X];
controllerData[0x01] = analogState[WiiAnalogs::WII_ANALOG_RIGHT_X];
controllerData[0x02] = analogState[WiiAnalogs::WII_ANALOG_LEFT_Y];
controllerData[0x03] = analogState[WiiAnalogs::WII_ANALOG_RIGHT_Y];
controllerData[0x04] = analogState[WiiAnalogs::WII_ANALOG_LEFT_TRIGGER];
controllerData[0x05] = analogState[WiiAnalogs::WII_ANALOG_RIGHT_TRIGGER];
controllerData[0x06] = (1 |
((!(buttons[WiiButtons::WII_BUTTON_R] & 0x01) << 1)) |
((!(buttons[WiiButtons::WII_BUTTON_PLUS] & 0x01) << 2)) |
((!(buttons[WiiButtons::WII_BUTTON_HOME] & 0x01) << 3)) |
((!(buttons[WiiButtons::WII_BUTTON_MINUS] & 0x01) << 4)) |
((!(buttons[WiiButtons::WII_BUTTON_L] & 0x01) << 5)) |
((!(buttons[WiiButtons::WII_BUTTON_DOWN] & 0x01) << 6)) |
((!(buttons[WiiButtons::WII_BUTTON_RIGHT] & 0x01) << 7))
);
controllerData[0x07] = (
((!(buttons[WiiButtons::WII_BUTTON_UP] & 0x01)) << 0) |
((!(buttons[WiiButtons::WII_BUTTON_LEFT] & 0x01)) << 1) |
((!(buttons[WiiButtons::WII_BUTTON_ZR] & 0x01)) << 2) |
((!(buttons[WiiButtons::WII_BUTTON_X] & 0x01)) << 3) |
((!(buttons[WiiButtons::WII_BUTTON_A] & 0x01)) << 4) |
((!(buttons[WiiButtons::WII_BUTTON_Y] & 0x01)) << 5) |
((!(buttons[WiiButtons::WII_BUTTON_B] & 0x01)) << 6) |
((!(buttons[WiiButtons::WII_BUTTON_ZL] & 0x01)) << 7)
);
return 8;
} else {
}

return 0;
}
1 change: 1 addition & 0 deletions lib/WiiExtension/extensions/ClassicExtension.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class ClassicExtension : public ExtensionBase {
void init(uint8_t dataType) override;
bool calibrate(uint8_t *calibrationData) override;
void process(uint8_t *inputData) override;
uint8_t prepareOutput() override;
};

#endif
112 changes: 111 additions & 1 deletion lib/WiiExtension/extensions/DrumExtension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,114 @@ void DrumExtension::process(uint8_t *inputData) {
// _lastRead[i] = inputData[i];
//}
#endif
}
}

uint8_t DrumExtension::prepareOutput() {
uint16_t lx = 0;
uint16_t ly = 0;
uint16_t rx = 0;
uint16_t ry = 0;
uint16_t lt = 0;
uint16_t rt = 0;
// expect all source analog sticks at 16 bit and scale down
// expect all source analog triggers at 8 bit and scale down
if (getDataType() == WII_DATA_TYPE_1) {
lx = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_LEFT_X] * 0x3F) / 0xFFFF);
ly = (uint8_t)(0x3F - ((analogState[WiiAnalogs::WII_ANALOG_LEFT_Y] * 0x3F) / 0xFFFF));
rx = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_RIGHT_X] * 0x1F) / 0xFFFF);
ry = (uint8_t)(0x1F - ((analogState[WiiAnalogs::WII_ANALOG_RIGHT_Y] * 0x1F) / 0xFFFF));
lt = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_LEFT_TRIGGER] * 0x1F) / 0xFF);
rt = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_RIGHT_TRIGGER] * 0x1F) / 0xFF);

controllerData[0x00] = 0xC0 | ((lx+1) & 0x3F);
controllerData[0x01] = 0xC0 | (ly & 0x3F);
controllerData[0x02] = 0xFF;
controllerData[0x03] = 0xFF;
controllerData[0x04] = (
((1 << 0)) |
((1 << 1)) |
((!(buttons[WiiButtons::WII_BUTTON_PLUS] & 0x01) << 2)) |
((1 << 3)) |
((!(buttons[WiiButtons::WII_BUTTON_MINUS] & 0x01) << 4)) |
((1 << 5)) |
((1 << 6)) |
((1 << 7))
);
controllerData[0x05] = (
((1 << 0)) |
((1 << 1)) |
((!(buttons[GuitarButtons::GUITAR_PEDAL] & 0x01) << 2)) |
((!(buttons[GuitarButtons::GUITAR_YELLOW] & 0x01) << 3)) |
((!(buttons[GuitarButtons::GUITAR_GREEN] & 0x01) << 4)) |
((!(buttons[GuitarButtons::GUITAR_BLUE] & 0x01) << 5)) |
((!(buttons[GuitarButtons::GUITAR_RED] & 0x01) << 6)) |
((!(buttons[GuitarButtons::GUITAR_ORANGE] & 0x01) << 7))
);
return 6;
} else if (getDataType() == WII_DATA_TYPE_2) {
lx = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_LEFT_X] * 0x3FF) / 0xFFFF);
ly = (uint8_t)(0x3F - ((analogState[WiiAnalogs::WII_ANALOG_LEFT_Y] * 0x3FF) / 0xFFFF));
rx = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_RIGHT_X] * 0x3FF) / 0xFFFF);
ry = (uint8_t)(0x1F - ((analogState[WiiAnalogs::WII_ANALOG_RIGHT_Y] * 0x3FF) / 0xFFFF));
lt = analogState[WiiAnalogs::WII_ANALOG_LEFT_TRIGGER];
rt = analogState[WiiAnalogs::WII_ANALOG_RIGHT_TRIGGER];

controllerData[0x00] = ((lx & 0x03FC) >> 2);
controllerData[0x01] = ((rx & 0x03FC) >> 2);
controllerData[0x02] = ((ly & 0x03FC) >> 2);
controllerData[0x03] = ((ry & 0x03FC) >> 2);
controllerData[0x04] = ((lx & 0x03) << 0) | ((rx & 0x03) << 2) | ((ly & 0x03) << 4) | ((ry & 0x03) << 6);
controllerData[0x05] = lt;
controllerData[0x06] = rt;
controllerData[0x07] = (1 |
((!(buttons[WiiButtons::WII_BUTTON_R] & 0x01) << 1)) |
((!(buttons[WiiButtons::WII_BUTTON_PLUS] & 0x01) << 2)) |
((!(buttons[WiiButtons::WII_BUTTON_HOME] & 0x01) << 3)) |
((!(buttons[WiiButtons::WII_BUTTON_MINUS] & 0x01) << 4)) |
((!(buttons[WiiButtons::WII_BUTTON_L] & 0x01) << 5)) |
((!(buttons[WiiButtons::WII_BUTTON_DOWN] & 0x01) << 6)) |
((!(buttons[WiiButtons::WII_BUTTON_RIGHT] & 0x01) << 7))
);
controllerData[0x08] = (
((!(buttons[WiiButtons::WII_BUTTON_UP] & 0x01)) << 0) |
((!(buttons[WiiButtons::WII_BUTTON_LEFT] & 0x01)) << 1) |
((!(buttons[WiiButtons::WII_BUTTON_ZR] & 0x01)) << 2) |
((!(buttons[WiiButtons::WII_BUTTON_X] & 0x01)) << 3) |
((!(buttons[WiiButtons::WII_BUTTON_A] & 0x01)) << 4) |
((!(buttons[WiiButtons::WII_BUTTON_Y] & 0x01)) << 5) |
((!(buttons[WiiButtons::WII_BUTTON_B] & 0x01)) << 6) |
((!(buttons[WiiButtons::WII_BUTTON_ZL] & 0x01)) << 7)
);
return 9;
} else if (getDataType() == WII_DATA_TYPE_3) {
controllerData[0x00] = analogState[WiiAnalogs::WII_ANALOG_LEFT_X];
controllerData[0x01] = analogState[WiiAnalogs::WII_ANALOG_RIGHT_X];
controllerData[0x02] = analogState[WiiAnalogs::WII_ANALOG_LEFT_Y];
controllerData[0x03] = analogState[WiiAnalogs::WII_ANALOG_RIGHT_Y];
controllerData[0x04] = analogState[WiiAnalogs::WII_ANALOG_LEFT_TRIGGER];
controllerData[0x05] = analogState[WiiAnalogs::WII_ANALOG_RIGHT_TRIGGER];
controllerData[0x06] = (1 |
((!(buttons[WiiButtons::WII_BUTTON_R] & 0x01) << 1)) |
((!(buttons[WiiButtons::WII_BUTTON_PLUS] & 0x01) << 2)) |
((!(buttons[WiiButtons::WII_BUTTON_HOME] & 0x01) << 3)) |
((!(buttons[WiiButtons::WII_BUTTON_MINUS] & 0x01) << 4)) |
((!(buttons[WiiButtons::WII_BUTTON_L] & 0x01) << 5)) |
((!(buttons[WiiButtons::WII_BUTTON_DOWN] & 0x01) << 6)) |
((!(buttons[WiiButtons::WII_BUTTON_RIGHT] & 0x01) << 7))
);
controllerData[0x07] = (
((!(buttons[WiiButtons::WII_BUTTON_UP] & 0x01)) << 0) |
((!(buttons[WiiButtons::WII_BUTTON_LEFT] & 0x01)) << 1) |
((!(buttons[WiiButtons::WII_BUTTON_ZR] & 0x01)) << 2) |
((!(buttons[WiiButtons::WII_BUTTON_X] & 0x01)) << 3) |
((!(buttons[WiiButtons::WII_BUTTON_A] & 0x01)) << 4) |
((!(buttons[WiiButtons::WII_BUTTON_Y] & 0x01)) << 5) |
((!(buttons[WiiButtons::WII_BUTTON_B] & 0x01)) << 6) |
((!(buttons[WiiButtons::WII_BUTTON_ZL] & 0x01)) << 7)
);
return 8;
} else {
}

return 0;
}
Loading