1
0
mirror of https://github.com/MickGyver/DaemonBite-Retro-Controllers-USB synced 2024-11-27 19:52:23 -05:00

Empty serial without the need to edit system libraries

This commit is contained in:
MickGyver 2020-02-13 18:53:51 +02:00
parent c098ddc905
commit 1cae9f1cbe
10 changed files with 104 additions and 76 deletions

View File

@ -23,11 +23,7 @@
#include "Gamepad.h" #include "Gamepad.h"
enum Mode #define BUTTON_READ_DELAY 300 // Button read delay in µs
{
TwoButton,
CD32
};
// Controller DB9 pins (looking face-on to the end of the plug): // Controller DB9 pins (looking face-on to the end of the plug):
// //
@ -40,15 +36,25 @@ enum Mode
// -------------------------------------- // --------------------------------------
// 1 TXO PD3 // 1 TXO PD3
// 2 RXI PD2 // 2 RXI PD2
// 3 3 PD0 // 3 3 PD0
// 4 4 PD4 // 4 4 PD4
// 5 A0 PF7 // 5 A0 PF7
// 6 6 PD7 // 6 6 PD7 (Important: Connect this pin via a 220Ω resistor!)
// 7 VCC // 7 VCC
// 8 GND // 8 GND
// 9 A1 PF6 // 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 // Set up USB HID gamepad
Gamepad_ Gamepad; Gamepad_ Gamepad;
@ -60,8 +66,12 @@ uint8_t axesPrev = 0;
uint8_t buttons = 0; uint8_t buttons = 0;
uint8_t buttonsPrev = 0; uint8_t buttonsPrev = 0;
Mode mode = CD32; // Timing
Mode modePrev = mode; long microsNow = 0;
long microsButtons = 0;
// CD32 controller detection
uint8_t detection = 0;
void setup() void setup()
{ {
@ -78,55 +88,56 @@ void setup()
void loop() void loop()
{ {
// Set mode from switch // Get current time
(PIND & B00000010) ? mode = CD32 : mode = TwoButton; microsNow = micros();
// Read X and Y axes // Read X and Y axes
axes = ~(PIND & B00011101); axes = ~(PIND & B00011101);
switch(mode) // See if enough time has passed since last button read
if(microsNow > microsButtons+BUTTON_READ_DELAY)
{ {
// Two button mode // Set pin 6 (clock, PD7) and pin 5 (latch, PF7) as output low
case TwoButton: 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 ); buttons = ~( ((PIND & B10000000) >> 7) | ((PINF & B01000000) >> 5) | B11111100 );
break;
microsButtons = microsNow+400;
// 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;
} }
// Has any buttons changed state? // Has any buttons changed state?
@ -146,6 +157,7 @@ void loop()
usbUpdate = true; usbUpdate = true;
} }
// Update USB data if necessary
if(usbUpdate) if(usbUpdate)
{ {
Gamepad.send(); Gamepad.send();
@ -156,8 +168,8 @@ void loop()
void sendClock() void sendClock()
{ {
// Send a clock pulse to pin 6 and wait // Send a clock pulse to pin 6 and wait
PORTD |= B10000000; PORTD |= B10000000; // Enable pull-up
delayMicroseconds(10); delayMicroseconds(10);
PORTD &= ~B10000000; PORTD &= ~B10000000; // Disable pull-up
delayMicroseconds(40); delayMicroseconds(40);
} }

View File

@ -143,3 +143,8 @@ void Gamepad_::send()
{ {
USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &_GamepadReport, sizeof(GamepadReport)); USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &_GamepadReport, sizeof(GamepadReport));
} }
uint8_t Gamepad_::getShortName(char *name)
{
return 0;
}

View File

@ -66,6 +66,7 @@ class Gamepad_ : public PluggableUSBModule
protected: protected:
int getInterface(uint8_t* interfaceCount); int getInterface(uint8_t* interfaceCount);
int getDescriptor(USBSetup& setup); int getDescriptor(USBSetup& setup);
uint8_t getShortName(char *name);
bool setup(USBSetup& setup); bool setup(USBSetup& setup);
uint8_t epType[1]; uint8_t epType[1];

View File

@ -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.

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 KiB

View File

@ -143,3 +143,8 @@ void Gamepad_::send()
{ {
USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &_GamepadReport, sizeof(GamepadReport)); USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &_GamepadReport, sizeof(GamepadReport));
} }
uint8_t Gamepad_::getShortName(char *name)
{
return 0;
}

View File

@ -29,12 +29,6 @@
#include <Arduino.h> #include <Arduino.h>
#include "HID.h" #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. // The numbers after colon are bit fields, meaning how many bits the field uses.
// Remove those if there are problems // Remove those if there are problems
typedef struct { typedef struct {
@ -66,6 +60,7 @@ class Gamepad_ : public PluggableUSBModule
protected: protected:
int getInterface(uint8_t* interfaceCount); int getInterface(uint8_t* interfaceCount);
int getDescriptor(USBSetup& setup); int getDescriptor(USBSetup& setup);
uint8_t getShortName(char *name);
bool setup(USBSetup& setup); bool setup(USBSetup& setup);
uint8_t epType[1]; uint8_t epType[1];

View File

@ -143,3 +143,8 @@ void Gamepad_::send()
{ {
USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &_GamepadReport, sizeof(GamepadReport)); USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &_GamepadReport, sizeof(GamepadReport));
} }
uint8_t Gamepad_::getShortName(char *name)
{
return 0;
}

View File

@ -29,12 +29,6 @@
#include <Arduino.h> #include <Arduino.h>
#include "HID.h" #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. // The numbers after colon are bit fields, meaning how many bits the field uses.
// Remove those if there are problems // Remove those if there are problems
typedef struct { typedef struct {
@ -66,6 +60,7 @@ class Gamepad_ : public PluggableUSBModule
protected: protected:
int getInterface(uint8_t* interfaceCount); int getInterface(uint8_t* interfaceCount);
int getDescriptor(USBSetup& setup); int getDescriptor(USBSetup& setup);
uint8_t getShortName(char *name);
bool setup(USBSetup& setup); bool setup(USBSetup& setup);
uint8_t epType[1]; uint8_t epType[1];

View File

@ -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 "SegaControllers32U4.h"
#include "Gamepad.h" #include "Gamepad.h"