diff --git a/CD32ControllerUSB/CD32ControllerUSB.ino b/CD32ControllerUSB/CD32ControllerUSB.ino index fac2fe2..b5b6932 100644 --- a/CD32ControllerUSB/CD32ControllerUSB.ino +++ b/CD32ControllerUSB/CD32ControllerUSB.ino @@ -23,11 +23,7 @@ #include "Gamepad.h" -enum Mode -{ - TwoButton, - CD32 -}; +#define BUTTON_READ_DELAY 300 // Button read delay in µs // Controller DB9 pins (looking face-on to the end of the plug): // @@ -40,15 +36,25 @@ enum Mode // -------------------------------------- // 1 TXO PD3 // 2 RXI PD2 -// 3 3 PD0 -// 4 4 PD4 +// 3 3 PD0 +// 4 4 PD4 // 5 A0 PF7 -// 6 6 PD7 +// 6 6 PD7 (Important: Connect this pin via a 220Ω resistor!) // 7 VCC // 8 GND // 9 A1 PF6 -// -// Connect a slide switch to pins GND,GND and 2 (PD1) +// ----------------- +// (Second controller port for future reference) +// 1 15 PB1 +// 2 14 PB3 +// 3 16 PB2 +// 4 10 PB6 +// 5 A2 PF5 +// 6 7 PE6 (Important: Connect this pin via a 220Ω resistor!) +// 7 VCC +// 8 GND +// 9 A3 PF4 + // Set up USB HID gamepad Gamepad_ Gamepad; @@ -60,8 +66,12 @@ uint8_t axesPrev = 0; uint8_t buttons = 0; uint8_t buttonsPrev = 0; -Mode mode = CD32; -Mode modePrev = mode; +// Timing +long microsNow = 0; +long microsButtons = 0; + +// CD32 controller detection +uint8_t detection = 0; void setup() { @@ -78,55 +88,56 @@ void setup() void loop() { - // Set mode from switch - (PIND & B00000010) ? mode = CD32 : mode = TwoButton; + // Get current time + microsNow = micros(); // Read X and Y axes axes = ~(PIND & B00011101); - switch(mode) + // See if enough time has passed since last button read + if(microsNow > microsButtons+BUTTON_READ_DELAY) { - // Two button mode - case TwoButton: + // Set pin 6 (clock, PD7) and pin 5 (latch, PF7) as output low + PORTD &= ~B10000000; // low to disable internal pull-up (will become low when set as output) + DDRD |= B10000000; // output + PORTF &= ~B10000000; // low to disable internal pull-up (will become low when set as output) + DDRF |= B10000000; // output + delayMicroseconds(40); + + // Clear buttons + buttons = 0; + + // Read buttons + (PINF & B01000000) ? buttons &= ~B00000010 : buttons |= B00000010; // Blue (2) + sendClock(); + (PINF & B01000000) ? buttons &= ~B00000001 : buttons |= B00000001; // Red (1) + sendClock(); + (PINF & B01000000) ? buttons &= ~B00001000 : buttons |= B00001000; // Yellow (4) + sendClock(); + (PINF & B01000000) ? buttons &= ~B00000100 : buttons |= B00000100; // Green (3) + sendClock(); + (PINF & B01000000) ? buttons &= ~B00100000 : buttons |= B00100000; // RTrig (6) + sendClock(); + (PINF & B01000000) ? buttons &= ~B00010000 : buttons |= B00010000; // LTrig (5) + sendClock(); + (PINF & B01000000) ? buttons &= ~B01000000 : buttons |= B01000000; // Play (7) + sendClock(); + (PINF & B01000000) ? detection |= B00000001 : detection &= ~B00000001; // First detection bit (should be 1) + sendClock(); + (PINF & B01000000) ? detection |= B00000010 : detection &= ~B00000010; // Second detection bit (should be 0) + + // Set pin 5 (latch, PF7) and pin 6 (clock, PD7) as input with pull-ups + DDRF &= ~B10000000; // input + PORTF |= B10000000; // high to enable internal pull-up + DDRD &= ~B10000000; // input + PORTD |= B10000000; // high to enable internal pull-up + delayMicroseconds(40); + + // Was a CD32 gamepad detected? If not, read button 1 and 2 "normally". + if(detection != B0000001) buttons = ~( ((PIND & B10000000) >> 7) | ((PINF & B01000000) >> 5) | B11111100 ); - break; - - // CD32 button mode - case CD32: - - // Set pin 6 (clock, PD7) and pin 5 (latch, PF7) as output low - PORTD &= ~B10000000; // low to disable internal pull-up (will become low when set as output) - DDRD |= B10000000; // output - PORTF &= ~B10000000; // low to disable internal pull-up (will become low when set as output) - DDRF |= B10000000; // output - delayMicroseconds(40); - - // Clear buttons - buttons = 0; - - // Read buttons - (PINF & B01000000) ? buttons &= ~B00000010 : buttons |= B00000010; // Blue (2) - sendClock(); - (PINF & B01000000) ? buttons &= ~B00000001 : buttons |= B00000001; // Red (1) - sendClock(); - (PINF & B01000000) ? buttons &= ~B00001000 : buttons |= B00001000; // Yellow (4) - sendClock(); - (PINF & B01000000) ? buttons &= ~B00000100 : buttons |= B00000100; // Green (3) - sendClock(); - (PINF & B01000000) ? buttons &= ~B00100000 : buttons |= B00100000; // RTrig (6) - sendClock(); - (PINF & B01000000) ? buttons &= ~B00010000 : buttons |= B00010000; // LTrig (5) - sendClock(); - (PINF & B01000000) ? buttons &= ~B01000000 : buttons |= B01000000; // Play (7) - - // Set pin 5 (latch, PF7) and pin 6 (clock, PD7) as input with pull-ups - DDRF &= ~B10000000; // input - PORTF |= B10000000; // high to enable internal pull-up - DDRD &= ~B10000000; // input - PORTD |= B10000000; // high to enable internal pull-up - delayMicroseconds(40); - - break; + + microsButtons = microsNow+400; } // Has any buttons changed state? @@ -146,6 +157,7 @@ void loop() usbUpdate = true; } + // Update USB data if necessary if(usbUpdate) { Gamepad.send(); @@ -156,8 +168,8 @@ void loop() void sendClock() { // Send a clock pulse to pin 6 and wait - PORTD |= B10000000; + PORTD |= B10000000; // Enable pull-up delayMicroseconds(10); - PORTD &= ~B10000000; - delayMicroseconds(40); + PORTD &= ~B10000000; // Disable pull-up + delayMicroseconds(40); } diff --git a/CD32ControllerUSB/Gamepad.cpp b/CD32ControllerUSB/Gamepad.cpp index 3efa039..eddab2b 100644 --- a/CD32ControllerUSB/Gamepad.cpp +++ b/CD32ControllerUSB/Gamepad.cpp @@ -143,3 +143,8 @@ void Gamepad_::send() { USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &_GamepadReport, sizeof(GamepadReport)); } + +uint8_t Gamepad_::getShortName(char *name) +{ + return 0; +} diff --git a/CD32ControllerUSB/Gamepad.h b/CD32ControllerUSB/Gamepad.h index 731c5fd..3468a9a 100644 --- a/CD32ControllerUSB/Gamepad.h +++ b/CD32ControllerUSB/Gamepad.h @@ -66,6 +66,7 @@ class Gamepad_ : public PluggableUSBModule protected: int getInterface(uint8_t* interfaceCount); int getDescriptor(USBSetup& setup); + uint8_t getShortName(char *name); bool setup(USBSetup& setup); uint8_t epType[1]; diff --git a/CD32ControllerUSB/README.md b/CD32ControllerUSB/README.md new file mode 100644 index 0000000..73071e9 --- /dev/null +++ b/CD32ControllerUSB/README.md @@ -0,0 +1,16 @@ +# DaemonBite-CD32-USB +## Introduction +With this simple to build adapter you can connect Amiga CD32 gamepads and Commodore/Amiga/Atari joysticks to a PC, Raspberry PI, MiSTer FPGA etc. The Arduino Pro Micro has very low lag when configured as a USB gamepad and it is plug n' play once it has been programmed. + +## Parts you need +- Arduino Pro Micro (ATMega32U4) +- Male end of Mega Drive controller extension (or DSUB 9Pin Male connector and some wires) +- 220Ω resistor +- Heat shrink tube (Ø ~20mm) +- Micro USB cable + +## Wiring +![Assemble1](images/cd32-usb-adapter-wiring.png) + +## License +This project is licensed under the GNU General Public License v3.0. diff --git a/CD32ControllerUSB/images/cd32-usb-adapter-wiring.png b/CD32ControllerUSB/images/cd32-usb-adapter-wiring.png new file mode 100644 index 0000000..fd96815 Binary files /dev/null and b/CD32ControllerUSB/images/cd32-usb-adapter-wiring.png differ diff --git a/SegaControllerUSB/Gamepad.cpp b/SegaControllerUSB/Gamepad.cpp index 3efa039..eddab2b 100644 --- a/SegaControllerUSB/Gamepad.cpp +++ b/SegaControllerUSB/Gamepad.cpp @@ -143,3 +143,8 @@ void Gamepad_::send() { USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &_GamepadReport, sizeof(GamepadReport)); } + +uint8_t Gamepad_::getShortName(char *name) +{ + return 0; +} diff --git a/SegaControllerUSB/Gamepad.h b/SegaControllerUSB/Gamepad.h index 731c5fd..a39ebdc 100644 --- a/SegaControllerUSB/Gamepad.h +++ b/SegaControllerUSB/Gamepad.h @@ -29,12 +29,6 @@ #include #include "HID.h" -// NOTE: To make this work on the MiSTer (or possibly other Linux distros), -// you need to edit USBDesc.h like follows. Change: -// #define ISERIAL 3 -// to -// #define ISERIAL 0 - // The numbers after colon are bit fields, meaning how many bits the field uses. // Remove those if there are problems typedef struct { @@ -66,6 +60,7 @@ class Gamepad_ : public PluggableUSBModule protected: int getInterface(uint8_t* interfaceCount); int getDescriptor(USBSetup& setup); + uint8_t getShortName(char *name); bool setup(USBSetup& setup); uint8_t epType[1]; diff --git a/SegaTwoControllersUSB/Gamepad.cpp b/SegaTwoControllersUSB/Gamepad.cpp index 3efa039..eddab2b 100644 --- a/SegaTwoControllersUSB/Gamepad.cpp +++ b/SegaTwoControllersUSB/Gamepad.cpp @@ -143,3 +143,8 @@ void Gamepad_::send() { USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &_GamepadReport, sizeof(GamepadReport)); } + +uint8_t Gamepad_::getShortName(char *name) +{ + return 0; +} diff --git a/SegaTwoControllersUSB/Gamepad.h b/SegaTwoControllersUSB/Gamepad.h index 731c5fd..a39ebdc 100644 --- a/SegaTwoControllersUSB/Gamepad.h +++ b/SegaTwoControllersUSB/Gamepad.h @@ -29,12 +29,6 @@ #include #include "HID.h" -// NOTE: To make this work on the MiSTer (or possibly other Linux distros), -// you need to edit USBDesc.h like follows. Change: -// #define ISERIAL 3 -// to -// #define ISERIAL 0 - // The numbers after colon are bit fields, meaning how many bits the field uses. // Remove those if there are problems typedef struct { @@ -66,6 +60,7 @@ class Gamepad_ : public PluggableUSBModule protected: int getInterface(uint8_t* interfaceCount); int getDescriptor(USBSetup& setup); + uint8_t getShortName(char *name); bool setup(USBSetup& setup); uint8_t epType[1]; diff --git a/SegaTwoControllersUSB/SegaTwoControllersUSB.ino b/SegaTwoControllersUSB/SegaTwoControllersUSB.ino index 24fb9f2..584f78e 100644 --- a/SegaTwoControllersUSB/SegaTwoControllersUSB.ino +++ b/SegaTwoControllersUSB/SegaTwoControllersUSB.ino @@ -21,12 +21,6 @@ * */ -// NOTE: To make this work on the MiSTer (or possibly other Linux distros), -// you need to edit USBDesc.h like follows. Change: -// #define ISERIAL 3 -// to -// #define ISERIAL 0 - #include "SegaControllers32U4.h" #include "Gamepad.h"