diff --git a/readme.md b/readme.md index c98d5eb..346c5e5 100644 --- a/readme.md +++ b/readme.md @@ -23,33 +23,33 @@ Wiring ![DB-25 Pinout](images/db25pins.jpg) -| DB-25 Male Pins | Arduino Pro Micro GPIO | ESP32 GPIO | -|--------------|---------------------------------------------|-----------------------------------------| -| 1 | 1 | | -| 2 | 2 | | -| 3 | 3 | | -| 4 | 4 | | -| 5 | 5 | | -| 6 | 6 | | -| 7 | 7 | | -| 8 | 8 | | -| 9 | 9 | | -| 10 | 10 | | -| 11 | 11 | | -| 12 | - | | -| 13 | - | | -| 14 | 14 | | -| 15 | 15 | | -| 16 | 16 | | -| 17 | - | | -| 18 | 18 | | -| 19 | 19 | | -| 20 | 20 | | -| 21 | 21 | | -| 22 | - | | -| 23 | 3.3V VCC | | -| 24 | 5V VCC | | -| 25 | GND | | +| DB-25 Pins | Arduino Pro Micro GPIO | ESP32 GPIO | RADIO | SNES | PSX | +|---------------|------------------------|------------|----------|--------|--------| +| 1 | 1 | | - | - | - | +| 2 | 2 | | - | LATCH | DATA | +| 3 | 3 | | - | CLOCK | CMD | +| 4 | 4 | | - | - | ATT | +| 5 | 5 | | - | - | CLK | +| 6 | 6 | | - | - | - | +| 7 | 7 | | CE | - | - | +| 8 | 8 | | CSN | - | - | +| 9 | 9 | | - | - | - | +| 10 | 10 | | - | - | - | +| 11 | 0 | | - | - | - | +| 12 | - | | - | - | - | +| 13 | - | | - | - | - | +| 14 | 14 | | MISO | - | - | +| 15 | 15 | | SCLK | - | - | +| 16 | 16 | | MOSI | - | - | +| 17 | - | | - | - | - | +| 18 | 18 | | - | DATA1 | - | +| 19 | 19 | | - | DATA2 | - | +| 20 | 20 | | - | DATA3 | - | +| 21 | 21 | | - | DATA4 | - | +| 22 | - | | - | - | - | +| 23 | - | | 3.3V VCC | - | - | +| 24 | 5V VCC | | 5V VCC | 5V VCC | 5V VCC | +| 25 | GND | | GND | GND | - | diff --git a/src/N64Micro.cpp b/src/N64Micro.cpp index d9fe665..2e57687 100644 --- a/src/N64Micro.cpp +++ b/src/N64Micro.cpp @@ -5,14 +5,14 @@ /-------------\ -PIN # USAGE +PIN # USAGE (colors from my extension cable, check your own) - GND - DATA - VCC +3.3V ONLY + GND - red + DATA - white + VCC +3.3V ONLY - black */ -#define DATA_PIN 7 +#define DATA_PIN 2 // how often to poll, 100? 14? polling must not occur faster than every 20 ms #define POLL_DELAY 14 @@ -123,6 +123,8 @@ void print_report(ControllerReport &controller) { #endif void setup() { + // n64 low because it *should* be 3.3V + digitalWrite(DATA_PIN, LOW); #ifdef DEBUG Serial.begin(115200); if (controller.begin()) { @@ -172,7 +174,7 @@ void loop() { gamepad.press(c, BUTTON_B); } if (report.z) { - gamepad.press(c, BUTTON_TR); + gamepad.press(c, BUTTON_TL2); } if (report.l) { gamepad.press(c, BUTTON_L); diff --git a/src/Playstation.cpp b/src/Playstation.cpp index 471e24a..af98161 100644 --- a/src/Playstation.cpp +++ b/src/Playstation.cpp @@ -8,17 +8,17 @@ \_____________________________/ -PIN # USAGE +PIN # USAGE (colors from my extension cable, check your own) - DATA - CMD/COMMAND - N/C (9 Volts unused) - GND - VCC - ATT - CLK/CLOCK - N/C - ACK + DATA - brown + CMD/COMMAND - orange + N/C (9 Volts unused) - white + GND - black + 5V VCC - red + ATT - yellow + CLK/CLOCK - blue + N/C - - + ACK - green */ diff --git a/src/SnesNes.cpp b/src/SnesNes.cpp index a40206a..76140e2 100644 --- a/src/SnesNes.cpp +++ b/src/SnesNes.cpp @@ -32,9 +32,14 @@ static const int CLOCK_PIN = 3; // white #endif // power red, ground black +//#define DEBUG + #include "gamepad/Gamepad.h" -static const int translateToNES[12] = {1, 8, 2, 3, 4, 5, 6, 7, 0, 8, 8, 8}; +static const uint8_t translateToNES[12] = {1, 8, 2, 3, 4, 5, 6, 7, 0, 8, 8, 8}; + +static const uint8_t nesButtons[4] = {0, 2, 3, 8}; +static const uint8_t snesButtons[8] = {0, 1, 2, 3, 8, 9, 10, 11}; class GameControllers { public: @@ -59,12 +64,12 @@ class GameControllers { L = 10, R = 11, }; - Type types[GAMEPAD_COUNT]; int latchPin; int clockPin; int dataPins[GAMEPAD_COUNT]; long buttons[GAMEPAD_COUNT][12]; + int maxButtons = 12; int changedControllers[GAMEPAD_COUNT]; @@ -76,13 +81,6 @@ class GameControllers { digitalWrite(latchPin, LOW); pinMode(clockPin, OUTPUT); digitalWrite(clockPin, HIGH); - for (int c = 0; c < GAMEPAD_COUNT; c++) { - for (int i = 0; i < 12; i++) { - buttons[c][i] = -1; - } - types[c] = NES; // todo: if SNES button is ever pressed, change type to SNES, maybe buttons to manually toggle? - dataPins[c] = -1; - } } ///This sets the controller type and initializes its individual data pin @@ -90,6 +88,9 @@ class GameControllers { types[controller] = type; dataPins[controller] = dataPin; pinMode(dataPins[controller], INPUT_PULLUP); + for (int i = 0; i < 12; i++) { + buttons[controller][i] = -1; + } } void poll(void (*controllerChanged)(const int controller)) { @@ -99,28 +100,33 @@ class GameControllers { delayMicroseconds(12); digitalWrite(latchPin, LOW); delayMicroseconds(6); - for (int i = 0; i < 12; i++) { - for (int c = 0; c < GAMEPAD_COUNT; c++) - if (dataPins[c] > -1) { - if (digitalRead(dataPins[c])) { - if (-1 != buttons[c][i]) { - buttons[c][i] = -1; - changedControllers[c] = 1; - } - } else { - //++buttons[c][i]; - //changedControllers[c] = 1; - if (0 != buttons[c][i]) { - buttons[c][i] = 0; - changedControllers[c] = 1; - } + //Serial.print("snes: "); + for (int i = 0; i < maxButtons; i++) { + for (int c = 0; c < GAMEPAD_COUNT; c++) { + if (digitalRead(dataPins[c])) { + // up + //Serial.print("-"); + if (-1 != buttons[c][i]) { + buttons[c][i] = -1; + changedControllers[c] = 1; + } + } else { + // down + //Serial.print(i); + //++buttons[c][i]; + //changedControllers[c] = 1; + if (0 != buttons[c][i]) { + buttons[c][i] = 0; + changedControllers[c] = 1; } } + } digitalWrite(clockPin, LOW); delayMicroseconds(6); digitalWrite(clockPin, HIGH); delayMicroseconds(6); } + //Serial.println(); for (int c = 0; c < GAMEPAD_COUNT; c++) { // have any buttons changed state? @@ -130,16 +136,32 @@ class GameControllers { } } - int translate(int controller, Button b) const { + uint8_t translate(int controller, uint8_t b) { if (types[controller] == SNES) return b; return translateToNES[b]; } ///returns if button is currently down - bool down(int controller, Button b) const { + bool down(int controller, uint8_t b) { return buttons[controller][translate(controller, b)] >= 0; } + + void pressAll(int controller, void (*pushButton)(const int controller, const uint8_t btn)) { + if (types[controller] == SNES) { + for (uint8_t i = 0; i < sizeof(snesButtons); i++) { + if (buttons[controller][snesButtons[i]] >= 0) { + pushButton(controller, snesButtons[i]); + } + } + } else { + for (uint8_t i = 0; i < sizeof(nesButtons); i++) { + if (buttons[controller][translateToNES[nesButtons[i]]] >= 0) { + pushButton(controller, nesButtons[i]); + } + } + } + } }; static const int translateToHid[12] = { @@ -161,19 +183,10 @@ GameControllers controllers; GAMEPAD_CLASS gamepad; -void setup() { - gamepad.begin(); - - //initialize shared pins - controllers.init(LATCH_PIN, CLOCK_PIN); - - //activate first controller ans set the type to SNES - for (int c = 0; c < GAMEPAD_COUNT; c++) { - controllers.setController(c, GameControllers::NES, DATA_PIN[c]); - } +void dummyControllerChanged(const int c) { } -/* +#ifdef DEBUG void controllerChangedDebug(const int c) { Serial.print("controllerChanged!!!!: "); Serial.println(c); @@ -183,14 +196,62 @@ void controllerChangedDebug(const int c) { Serial.print("; "); Serial.print(btn); Serial.print(", "); - Serial.print(controllers.buttons[c][controllers.translate(c, static_cast(btn))]); + Serial.print(controllers.buttons[c][controllers.translate(c, btn)]); + Serial.print(","); + Serial.print(controllers.buttons[c][btn]); } Serial.println(""); } -*/ +#endif // DEBUG + +void setup() { + bool allNes = true; +#ifdef DEBUG + delay(5000); +#endif // DEBUG + gamepad.begin(); + + //initialize shared pins + controllers.init(LATCH_PIN, CLOCK_PIN); + + //activate first controller and set the type to SNES + for (int c = 0; c < GAMEPAD_COUNT; c++) { + controllers.setController(c, GameControllers::SNES, DATA_PIN[c]); + } + + // poll controllers once to detect NES vs SNES + controllers.poll(dummyControllerChanged); + + for (int c = 0; c < GAMEPAD_COUNT; c++) { + // for NES, A+X+L+R are down always, re-initialize + if (controllers.down(c, GameControllers::A) && controllers.down(c, GameControllers::X) && controllers.down(c, GameControllers::L) && controllers.down(c, GameControllers::R)) { +#ifdef DEBUG + Serial.println("detected NES"); +#endif // DEBUG + controllers.types[c] = GameControllers::NES; + } else { +#ifdef DEBUG + Serial.println("detected SNES"); +#endif // DEBUG + allNes = false; + } + } + if (allNes) { +#ifdef DEBUG + Serial.println("detected ONLY NES"); +#endif // DEBUG + controllers.maxButtons = 8; + } +} + +void pushButton(const int c, const uint8_t btn) { + gamepad.press(c, translateToHid[btn]); +} void controllerChanged(const int c) { - //controllerChangedDebug(c); +#ifdef DEBUG + controllerChangedDebug(c); +#endif // DEBUG gamepad.buttons(c, 0); // if start and select are held at the same time, send menu and only menu @@ -198,13 +259,7 @@ void controllerChanged(const int c) { gamepad.press(c, BUTTON_MENU); } else { // actually send buttons held - for (uint8_t btn = 0; btn < 12; btn++) { - if (btn > 3 && btn < 8) - continue; // skip dpad - if (controllers.down(c, static_cast(btn))) { - gamepad.press(c, translateToHid[btn]); - } - } + controllers.pressAll(c, pushButton); } if (controllers.down(c, GameControllers::DOWN)) { if (controllers.down(c, GameControllers::RIGHT)) { diff --git a/src/gamepad/Debug-Gamepad/DebugGamepad.h b/src/gamepad/Debug-Gamepad/DebugGamepad.h index 911194a..71dbedd 100644 --- a/src/gamepad/Debug-Gamepad/DebugGamepad.h +++ b/src/gamepad/Debug-Gamepad/DebugGamepad.h @@ -9,6 +9,19 @@ #include "../common.h" +void print_axis(int16_t i) { + char buf[6]; + sprintf(buf, i < 0 ? "%05d" : "+%05d", i); + Serial.print(buf); +} + +void print_trigger(char i) { + char buf[4] = {0}; // why the hell is this initializer required... + // todo: probably not right + sprintf(buf, "%03u", (uint8_t)i); + Serial.print(buf); +} + class DebugGamepad : public AbstractGamepad { public: DebugGamepad() : AbstractGamepad() { @@ -20,7 +33,80 @@ class DebugGamepad : public AbstractGamepad { } virtual void setAxis(const uint8_t cIdx, int16_t x, int16_t y, int16_t z, int16_t rZ, char rX, char rY, signed char hat) { - Serial.println("DebugGamepad.setAxis"); + Serial.print("DebugGamepad.setAxis "); + Serial.print(cIdx); + Serial.print(" b: "); + Serial.print(this->isPressed(cIdx, BUTTON_A) ? "A" : "-"); + Serial.print("+"); + Serial.print(this->isPressed(cIdx, BUTTON_B) ? "B" : "-"); + Serial.print("+"); + Serial.print(this->isPressed(cIdx, BUTTON_X) ? "X" : "-"); + Serial.print("+"); + Serial.print(this->isPressed(cIdx, BUTTON_Y) ? "Y" : "-"); + Serial.print("+"); + Serial.print(this->isPressed(cIdx, BUTTON_SELECT) ? "SL" : "--"); + Serial.print("+"); + Serial.print(this->isPressed(cIdx, BUTTON_START) ? "ST" : "--"); + Serial.print("+"); + Serial.print(this->isPressed(cIdx, BUTTON_MENU) ? "M" : "-"); + Serial.print("+"); + Serial.print(this->isPressed(cIdx, BUTTON_TL) ? "TL" : "--"); + Serial.print("+"); + Serial.print(this->isPressed(cIdx, BUTTON_TR) ? "TR" : "--"); + Serial.print("+"); + Serial.print(this->isPressed(cIdx, BUTTON_TL2) ? "TL2" : "---"); + Serial.print("+"); + Serial.print(this->isPressed(cIdx, BUTTON_TR2) ? "TR2" : "---"); + Serial.print("+"); + Serial.print(this->isPressed(cIdx, BUTTON_THUMBL) ? "THL" : "---"); + Serial.print("+"); + Serial.print(this->isPressed(cIdx, BUTTON_THUMBR) ? "THR" : "---"); + Serial.print(" h: "); + switch (hat) { + case DPAD_CENTER: + Serial.print("--"); + break; + case DPAD_UP: + Serial.print("U-"); + break; + case DPAD_UP_RIGHT: + Serial.print("UR"); + break; + case DPAD_RIGHT: + Serial.print("-R"); + break; + case DPAD_DOWN_RIGHT: + Serial.print("DR"); + break; + case DPAD_DOWN: + Serial.print("D-"); + break; + case DPAD_DOWN_LEFT: + Serial.print("DL"); + break; + case DPAD_LEFT: + Serial.print("-L"); + break; + case DPAD_UP_LEFT: + Serial.print("UL"); + break; + default: + Serial.print("++"); + break; + } + Serial.print(" X,Y: "); + print_axis(x); + Serial.print(","); + print_axis(y); + Serial.print(" Z,RZ: "); + print_axis(z); + Serial.print(","); + print_axis(rZ); + Serial.print(" rx: "); + print_trigger(rX); + Serial.print(" ry: "); + print_trigger(rY); + Serial.println(); AbstractGamepad::setAxis(cIdx, x, y, z, rZ, rX, rY, hat); } diff --git a/src/gamepad/UsbRadio-Gamepad/UsbRadioGamepad.h b/src/gamepad/UsbRadio-Gamepad/UsbRadioGamepad.h index f114f64..1b14080 100644 --- a/src/gamepad/UsbRadio-Gamepad/UsbRadioGamepad.h +++ b/src/gamepad/UsbRadio-Gamepad/UsbRadioGamepad.h @@ -4,7 +4,7 @@ // number of button presses we wait for USB-HID to connect // works within 1 for me but who knows... #ifndef GAMEPAD_USBRADIO_DETECT_BUTTONS -#define GAMEPAD_USBRADIO_DETECT_BUTTONS 1 +#define GAMEPAD_USBRADIO_DETECT_BUTTONS 4 #endif #ifndef GAMEPAD_CLASS