

1 changed files with 489 additions and 0 deletions
@ -0,0 +1,489 @@
@@ -0,0 +1,489 @@
|
||||
// https://github.com/SukkoPera/PsxNewLib
|
||||
// https://github.com/dmadison/ArduinoXInput
|
||||
|
||||
#define XINPUT |
||||
|
||||
#ifdef XINPUT |
||||
#include <XInput.h> |
||||
#endif |
||||
|
||||
#ifndef XINPUT |
||||
#define DEBUG |
||||
#endif |
||||
|
||||
#include <DigitalIO.h> |
||||
#include <PsxControllerHwSpi.h> |
||||
|
||||
#include <NintendoExtensionCtrl.h> |
||||
ClassicController classic; |
||||
|
||||
|
||||
#include <avr/pgmspace.h> |
||||
typedef const __FlashStringHelper * FlashStr; |
||||
typedef const byte* PGM_BYTES_P; |
||||
#define PSTR_TO_F(s) reinterpret_cast<const __FlashStringHelper *> (s) |
||||
|
||||
// This can be changed freely but please see above
|
||||
const byte PIN_PS2_ATT = 10; |
||||
|
||||
const byte PIN_BUTTONPRESS = A0; |
||||
const byte PIN_HAVECONTROLLER = A1; |
||||
|
||||
bool dirty = true; |
||||
bool wii; |
||||
|
||||
const char buttonSelectName[] PROGMEM = "Select"; |
||||
const char buttonL3Name[] PROGMEM = "L3"; |
||||
const char buttonR3Name[] PROGMEM = "R3"; |
||||
const char buttonStartName[] PROGMEM = "Start"; |
||||
const char buttonUpName[] PROGMEM = "Up"; |
||||
const char buttonRightName[] PROGMEM = "Right"; |
||||
const char buttonDownName[] PROGMEM = "Down"; |
||||
const char buttonLeftName[] PROGMEM = "Left"; |
||||
const char buttonL2Name[] PROGMEM = "L2"; |
||||
const char buttonR2Name[] PROGMEM = "R2"; |
||||
const char buttonL1Name[] PROGMEM = "L1"; |
||||
const char buttonR1Name[] PROGMEM = "R1"; |
||||
const char buttonTriangleName[] PROGMEM = "Triangle"; |
||||
const char buttonCircleName[] PROGMEM = "Circle"; |
||||
const char buttonCrossName[] PROGMEM = "Cross"; |
||||
const char buttonSquareName[] PROGMEM = "Square"; |
||||
|
||||
|
||||
#define PS_select (psxButtons & ( 1 << 0 )) |
||||
#define PS_L3 (psxButtons & ( 1 << 1 )) |
||||
#define PS_R3 (psxButtons & ( 1 << 2 )) |
||||
#define PS_start (psxButtons & ( 1 << 3 )) |
||||
#define PS_up (psxButtons & ( 1 << 4 )) |
||||
#define PS_right (psxButtons & ( 1 << 5 )) |
||||
#define PS_down (psxButtons & ( 1 << 6 )) |
||||
#define PS_left (psxButtons & ( 1 << 7 )) |
||||
#define PS_L2 (psxButtons & ( 1 << 8 )) |
||||
#define PS_R2 (psxButtons & ( 1 << 9 )) |
||||
#define PS_L1 (psxButtons & ( 1 << 10 )) |
||||
#define PS_R1 (psxButtons & ( 1 << 11 )) |
||||
#define PS_T (psxButtons & ( 1 << 12 )) |
||||
#define PS_O (psxButtons & ( 1 << 13 )) |
||||
#define PS_X (psxButtons & ( 1 << 14 )) |
||||
#define PS_S (psxButtons & ( 1 << 15 )) |
||||
|
||||
#define PS_LX (((uint16_t)lx*257)-32768) // 0..255 -> -32768..32767
|
||||
#define PS_LY (((255-(uint16_t)ly)*257)-32768) // 0..255 -> 32767..-32768
|
||||
#define PS_RX (((uint16_t)rx*257)-32768) // 0..255 -> -32768..32767
|
||||
#define PS_RY (((255-(uint16_t)ry)*257)-32768) // 0..255 -> 32767..-32768
|
||||
//psxnelib: left-right: 0...255 down-up: 255...0, xinput: left-right: -32768..32767, down-up: 32767..-32768
|
||||
|
||||
/*#define WII_LX (((uint16_t)joyLX*257)-32768) // 0..255 -> -32768..32767
|
||||
#define WII_LY (((uint16_t)joyLY*257)-32768) // 0..255 -> -32768..32767
|
||||
#define WII_RX (((uint16_t)joyRX*257)-32768) // 0..255 -> -32768..32767
|
||||
#define WII_RY (((uint16_t)joyRY*257)-32768) // 0..255 -> -32768..32767*/
|
||||
//#define WII_MAP(a) map(a, 28, 234, -32768, 32767)
|
||||
#define WII_MAP(a) map(a, 30, 230, -32768, 32767) |
||||
//nintendoremotectrl: left-right: 0...255 down-up: 0...255, xinput: left-right: -32768..32767, down-up: 32767..-32768
|
||||
|
||||
const char* const psxButtonNames[PSX_BUTTONS_NO] PROGMEM = { |
||||
buttonSelectName, |
||||
buttonL3Name, |
||||
buttonR3Name, |
||||
buttonStartName, |
||||
buttonUpName, |
||||
buttonRightName, |
||||
buttonDownName, |
||||
buttonLeftName, |
||||
buttonL2Name, |
||||
buttonR2Name, |
||||
buttonL1Name, |
||||
buttonR1Name, |
||||
buttonTriangleName, |
||||
buttonCircleName, |
||||
buttonCrossName, |
||||
buttonSquareName |
||||
}; |
||||
|
||||
byte psxButtonToIndex (PsxButtons psxButtons) { |
||||
byte i; |
||||
|
||||
for (i = 0; i < PSX_BUTTONS_NO; ++i) { |
||||
if (psxButtons & 0x01) { |
||||
break; |
||||
} |
||||
|
||||
psxButtons >>= 1U; |
||||
} |
||||
|
||||
return i; |
||||
} |
||||
|
||||
FlashStr getButtonName (PsxButtons psxButton) { |
||||
FlashStr ret = F(""); |
||||
|
||||
byte b = psxButtonToIndex (psxButton); |
||||
if (b < PSX_BUTTONS_NO) { |
||||
PGM_BYTES_P bName = reinterpret_cast<PGM_BYTES_P> (pgm_read_ptr (&(psxButtonNames[b]))); |
||||
ret = PSTR_TO_F (bName); |
||||
} |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
void dumpButtons (PsxButtons psxButtons) { |
||||
static PsxButtons lastB = 0; |
||||
|
||||
if (psxButtons != lastB) { |
||||
lastB = psxButtons; // Save it before we alter it
|
||||
|
||||
#ifdef DEBUG |
||||
Serial.print (F("Pressed: ")); |
||||
|
||||
for (byte i = 0; i < PSX_BUTTONS_NO; ++i) { |
||||
byte b = psxButtonToIndex (psxButtons); |
||||
if (b < PSX_BUTTONS_NO) { |
||||
PGM_BYTES_P bName = reinterpret_cast<PGM_BYTES_P> (pgm_read_ptr (&(psxButtonNames[b]))); |
||||
Serial.print (PSTR_TO_F (bName)); |
||||
} |
||||
|
||||
psxButtons &= ~(1 << b); |
||||
|
||||
if (psxButtons != 0) { |
||||
Serial.print (F(", ")); |
||||
} |
||||
} |
||||
Serial.println (); |
||||
#endif |
||||
|
||||
#ifdef XINPUT |
||||
if (PS_select) XInput.press(BUTTON_BACK); else XInput.release(BUTTON_BACK); //btn_7
|
||||
if (PS_start) XInput.press(BUTTON_START); else XInput.release(BUTTON_START); //btn_8
|
||||
if (PS_L3) XInput.press(BUTTON_L3); else XInput.release(BUTTON_L3); //btn_9
|
||||
if (PS_R3) XInput.press(BUTTON_R3); else XInput.release(BUTTON_R3); //btn_10
|
||||
XInput.setDpad(PS_up, PS_down, PS_left, PS_right); |
||||
if (PS_X) XInput.press(BUTTON_A); else XInput.release(BUTTON_A); //btn_1
|
||||
if (PS_O) XInput.press(BUTTON_B); else XInput.release(BUTTON_B); //btn_2
|
||||
if (PS_S) XInput.press(BUTTON_X); else XInput.release(BUTTON_X); //btn_3
|
||||
if (PS_T) XInput.press(BUTTON_Y); else XInput.release(BUTTON_Y); //btn_4
|
||||
if (PS_L1) XInput.press(BUTTON_LB); else XInput.release(BUTTON_LB); //btn_5
|
||||
if (PS_R1) XInput.press(BUTTON_RB); else XInput.release(BUTTON_RB); //btn_6
|
||||
if (PS_L2) XInput.setTrigger(TRIGGER_LEFT, 255); else XInput.setTrigger(TRIGGER_LEFT, 0); |
||||
if (PS_R2) XInput.setTrigger(TRIGGER_RIGHT, 255); else XInput.setTrigger(TRIGGER_RIGHT, 0); |
||||
dirty = true; |
||||
#endif |
||||
} |
||||
} |
||||
|
||||
void dumpAnalog (const char *str, const byte x, const byte y) { |
||||
#ifdef DEBUG |
||||
Serial.print (str); |
||||
Serial.print (F(" analog: x = ")); |
||||
Serial.print (x); |
||||
Serial.print (F(", y = ")); |
||||
Serial.println (y); |
||||
#endif |
||||
} |
||||
|
||||
|
||||
const char ctrlTypeUnknown[] PROGMEM = "Unknown"; |
||||
const char ctrlTypeDualShock[] PROGMEM = "Dual Shock"; |
||||
const char ctrlTypeDsWireless[] PROGMEM = "Dual Shock Wireless"; |
||||
const char ctrlTypeGuitHero[] PROGMEM = "Guitar Hero"; |
||||
const char ctrlTypeOutOfBounds[] PROGMEM = "(Out of bounds)"; |
||||
|
||||
const char* const controllerTypeStrings[PSCTRL_MAX + 1] PROGMEM = { |
||||
ctrlTypeUnknown, |
||||
ctrlTypeDualShock, |
||||
ctrlTypeDsWireless, |
||||
ctrlTypeGuitHero, |
||||
ctrlTypeOutOfBounds |
||||
}; |
||||
|
||||
PsxControllerHwSpi<PIN_PS2_ATT> psx; |
||||
|
||||
boolean haveController = false; |
||||
|
||||
|
||||
void setup () { |
||||
pinMode(4, INPUT); //check wii extension controller "detect device" line
|
||||
delay(100); |
||||
wii = digitalRead(4); |
||||
|
||||
//PsxNewLib
|
||||
fastPinMode (PIN_BUTTONPRESS, OUTPUT); |
||||
fastPinMode (PIN_HAVECONTROLLER, OUTPUT); |
||||
delay (300); |
||||
|
||||
#ifdef DEBUG |
||||
Serial.begin (115200); |
||||
while(!Serial); |
||||
Serial.println (F("Ready!")); |
||||
#endif |
||||
|
||||
#ifdef XINPUT |
||||
XInput.setAutoSend(false); |
||||
XInput.begin(); |
||||
#endif |
||||
|
||||
// NintendoExtensionCtrl
|
||||
if (wii) { |
||||
classic.begin(); |
||||
while (!classic.connect()) { |
||||
#ifdef DEBUG |
||||
Serial.println("Classic Controller not detected!"); |
||||
#endif |
||||
delay(1000); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
void loop () { |
||||
if(!wii) { |
||||
static byte slx, sly, srx, sry, sl2, sr2; |
||||
fastDigitalWrite (PIN_HAVECONTROLLER, haveController); |
||||
|
||||
if (!haveController) { |
||||
if (psx.begin ()) { |
||||
#ifdef DEBUG |
||||
Serial.println (F("Controller found!")); |
||||
#endif |
||||
delay (300); |
||||
if (!psx.enterConfigMode ()) { |
||||
#ifdef DEBUG |
||||
Serial.println (F("Cannot enter config mode")); |
||||
#endif |
||||
} else { |
||||
PsxControllerType ctype = psx.getControllerType (); |
||||
PGM_BYTES_P cname = reinterpret_cast<PGM_BYTES_P> (pgm_read_ptr (&(controllerTypeStrings[ctype < PSCTRL_MAX ? static_cast<byte> (ctype) : PSCTRL_MAX]))); |
||||
#ifdef DEBUG |
||||
Serial.print (F("Controller Type is: ")); |
||||
Serial.println (PSTR_TO_F (cname)); |
||||
#endif |
||||
|
||||
if (!psx.enableAnalogSticks ()) { |
||||
#ifdef DEBUG |
||||
Serial.println (F("Cannot enable analog sticks")); |
||||
#endif |
||||
} |
||||
|
||||
//~ if (!psx.setAnalogMode (false)) {
|
||||
//~ Serial.println (F("Cannot disable analog mode"));
|
||||
//~ }
|
||||
//~ delay (10);
|
||||
|
||||
if (!psx.enableAnalogButtons ()) { |
||||
#ifdef DEBUG |
||||
Serial.println (F("Cannot enable analog buttons")); |
||||
#endif |
||||
} |
||||
|
||||
if (!psx.exitConfigMode ()) { |
||||
#ifdef DEBUG |
||||
Serial.println (F("Cannot exit config mode")); |
||||
#endif |
||||
} |
||||
} |
||||
|
||||
haveController = true; |
||||
} |
||||
} else { |
||||
if (!psx.read ()) { |
||||
#ifdef DEBUG |
||||
Serial.println (F("Controller lost :(")); |
||||
#endif |
||||
haveController = false; |
||||
} else { |
||||
fastDigitalWrite (PIN_BUTTONPRESS, !!psx.getButtonWord ()); |
||||
dumpButtons (psx.getButtonWord ()); |
||||
|
||||
byte lx, ly; |
||||
psx.getLeftAnalog (lx, ly); |
||||
if (lx != slx || ly != sly) { |
||||
dumpAnalog ("Left", lx, ly); |
||||
#ifdef XINPUT |
||||
XInput.setJoystick(JOY_LEFT, PS_LX, PS_LY); //psxnelib: left-right: 0...255 down-up: 255...0, xinput: left-right: -32768..32767, down-up: 32767..-32768
|
||||
dirty = true; |
||||
#endif |
||||
slx = lx; |
||||
sly = ly; |
||||
} |
||||
|
||||
byte rx, ry; |
||||
psx.getRightAnalog (rx, ry); |
||||
if (rx != srx || ry != sry) { |
||||
dumpAnalog ("Right", rx, ry); |
||||
#ifdef XINPUT |
||||
XInput.setJoystick(JOY_RIGHT, PS_RX, PS_RY); //psxnelib: left-right: 0...255 down-up: 255...0, xinput: left-right: -32768..32767, down-up: 32767..-32768
|
||||
dirty = true; |
||||
#endif |
||||
srx = rx; |
||||
sry = ry; |
||||
} |
||||
|
||||
byte l2 = psx.getAnalogButton(PSAB_L2); |
||||
if (l2 != 0 && l2 != sl2) { |
||||
#ifdef DEBUG |
||||
Serial.println(l2); |
||||
#endif |
||||
#ifdef XINPUT |
||||
XInput.setTrigger(TRIGGER_LEFT, l2); |
||||
dirty = true; |
||||
#endif |
||||
sl2 = l2; |
||||
} |
||||
|
||||
byte r2 = psx.getAnalogButton(PSAB_R2); |
||||
if (r2 != 0 && r2 != sr2) { |
||||
#ifdef DEBUG |
||||
Serial.println(r2); |
||||
#endif |
||||
#ifdef XINPUT |
||||
XInput.setTrigger(TRIGGER_RIGHT, r2); |
||||
dirty = true; |
||||
#endif |
||||
sr2 = r2; |
||||
} |
||||
|
||||
} |
||||
} |
||||
} else { |
||||
|
||||
static byte sjoyLX, sjoyLY, sjoyRX, sjoyRY, striggerL, striggerR, spadUp, spadDown, spadLeft, spadRight, sbx, sby, sba, sbb, sbselect, sbhome, sbstart, sbzl, sbzr; |
||||
|
||||
boolean success = classic.update(); // Get new data from the controller
|
||||
|
||||
if (!success) { // Ruh roh
|
||||
#ifdef DEBUG |
||||
Serial.println("Controller disconnected!"); |
||||
#endif |
||||
delay(1000); |
||||
} else { |
||||
|
||||
boolean padUp = classic.dpadUp(); |
||||
boolean padDown = classic.dpadDown(); |
||||
boolean padLeft = classic.dpadLeft(); |
||||
boolean padRight = classic.dpadRight(); |
||||
if (padUp != spadUp || padDown != spadDown || padLeft != spadLeft || padRight != spadRight) { |
||||
XInput.setDpad(padUp, padDown, padLeft, padRight); |
||||
dirty = true; |
||||
spadUp = padUp; |
||||
spadDown = padDown; |
||||
spadLeft = padLeft; |
||||
spadRight = padRight; |
||||
} |
||||
|
||||
//sbx, sby, sba, sbb, sbselect, sbhome, sbstart, sbzl, sbzr;
|
||||
// Read a button (ABXY, Minus, Home, Plus, L, R, ZL, ZR)
|
||||
boolean aButton = classic.buttonA(); |
||||
if (aButton != sba) { |
||||
if (aButton) XInput.press(BUTTON_B); else XInput.release(BUTTON_B); |
||||
dirty = true; |
||||
sba = aButton; |
||||
}
|
||||
boolean bButton = classic.buttonB(); |
||||
if (bButton != sbb) { |
||||
if (bButton) XInput.press(BUTTON_A); else XInput.release(BUTTON_A); |
||||
dirty = true; |
||||
sbb = bButton; |
||||
}
|
||||
boolean xButton = classic.buttonX(); |
||||
if (xButton != sbx) { |
||||
if (xButton) XInput.press(BUTTON_Y); else XInput.release(BUTTON_Y); |
||||
dirty = true; |
||||
sbx = xButton; |
||||
}
|
||||
boolean yButton = classic.buttonY(); |
||||
if (yButton != sby) { |
||||
if (yButton) XInput.press(BUTTON_X); else XInput.release(BUTTON_X); |
||||
dirty = true; |
||||
sby = yButton; |
||||
}
|
||||
boolean buttonMinus = classic.buttonMinus(); |
||||
if (buttonMinus != sbselect) { |
||||
if (buttonMinus) XInput.press(BUTTON_BACK); else XInput.release(BUTTON_BACK); |
||||
dirty = true; |
||||
sbselect = buttonMinus; |
||||
}
|
||||
boolean buttonHome = classic.buttonHome(); |
||||
if (buttonHome != sbhome) { |
||||
if (buttonHome) XInput.press(BUTTON_LOGO); else XInput.release(BUTTON_LOGO); |
||||
dirty = true; |
||||
sbhome = buttonHome; |
||||
}
|
||||
boolean buttonPlus = classic.buttonPlus(); |
||||
if (buttonPlus != sbstart) { |
||||
if (buttonPlus) XInput.press(BUTTON_START); else XInput.release(BUTTON_START); |
||||
dirty = true; |
||||
sbstart = buttonPlus; |
||||
}
|
||||
boolean buttonZL = classic.buttonZL(); |
||||
if (buttonZL != sbzl) { |
||||
if (buttonZL) XInput.press(BUTTON_LB); else XInput.release(BUTTON_LB); |
||||
dirty = true; |
||||
sbzl = buttonZL; |
||||
}
|
||||
boolean buttonZR = classic.buttonZR(); |
||||
if (buttonZR != sbzr) { |
||||
if (buttonZR) XInput.press(BUTTON_RB); else XInput.release(BUTTON_RB); |
||||
dirty = true; |
||||
sbzr = buttonZR; |
||||
}
|
||||
|
||||
int triggerL = classic.triggerL(); |
||||
if (triggerL != striggerL) { |
||||
#ifdef XINPUT |
||||
XInput.setTrigger(TRIGGER_LEFT, triggerL); |
||||
dirty = true; |
||||
striggerL = triggerL; |
||||
#endif |
||||
}
|
||||
int triggerR = classic.triggerR(); |
||||
if (triggerR != striggerR) { |
||||
#ifdef XINPUT |
||||
XInput.setTrigger(TRIGGER_RIGHT, triggerR); |
||||
dirty = true; |
||||
striggerR = triggerR; |
||||
#endif |
||||
}
|
||||
int joyLX = classic.leftJoyX(); |
||||
int joyLY = classic.leftJoyY(); |
||||
if (joyLX != sjoyLX || joyLY != sjoyLY) { |
||||
#ifdef XINPUT |
||||
XInput.setJoystick(JOY_LEFT, WII_MAP(joyLX), WII_MAP(joyLY)); |
||||
dirty = true; |
||||
sjoyLX = joyLX; |
||||
sjoyLY = joyLY; |
||||
#endif |
||||
} |
||||
int joyRX = classic.rightJoyX(); |
||||
int joyRY = classic.rightJoyY(); |
||||
if (joyRX != sjoyRX || joyRY != sjoyRY) { |
||||
#ifdef XINPUT |
||||
XInput.setJoystick(JOY_RIGHT, WII_MAP(joyRX), WII_MAP(joyRY)); |
||||
dirty = true; |
||||
sjoyRX = joyRX; |
||||
sjoyRY = joyRY; |
||||
#endif |
||||
} |
||||
|
||||
#ifdef DEBUG |
||||
Serial.print(WII_MAP(joyLX)); Serial.print(" "); Serial.print(WII_MAP(joyLY)); Serial.print(" "); Serial.print(WII_MAP(joyRX));Serial.print(" "); Serial.print(WII_MAP(joyRY)); |
||||
Serial.println(); |
||||
//classic.printDebug();
|
||||
#endif |
||||
|
||||
} |
||||
}
|
||||
//delay (1000 / 60);
|
||||
#ifdef XINPUT |
||||
if (dirty) { |
||||
XInput.send(); |
||||
dirty = false; |
||||
} |
||||
#endif |
||||
|
||||
#ifdef DEBUG |
||||
delay(100); |
||||
#endif |
||||
|
||||
//delayMicroseconds(1000);
|
||||
delay(10); |
||||
|
||||
} |
Loading…
Reference in new issue