diff --git a/PSXControllerUSB/Gamepad.cpp b/PSXControllerUSB/Gamepad.cpp
new file mode 100644
index 0000000..7fe0edf
--- /dev/null
+++ b/PSXControllerUSB/Gamepad.cpp
@@ -0,0 +1,156 @@
+/* Gamepad.cpp
+ *
+ * Based on the advanced HID library for Arduino:
+ * https://github.com/NicoHood/HID
+ * Copyright (c) 2014-2015 NicoHood
+ *
+ * Copyright (c) 2021 Hendrik Osterholz
+ *
+ * GNU GENERAL PUBLIC LICENSE
+ * Version 3, 29 June 2007
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#include "Gamepad.h"
+
+static const uint8_t _hidReportDescriptor[] PROGMEM = {
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+ 0x09, 0x04, // USAGE (Joystick) (Maybe change to gamepad? I don't think so but...)
+ 0xa1, 0x01, // COLLECTION (Application)
+ 0xa1, 0x00, // COLLECTION (Physical)
+
+ 0x05, 0x09, // USAGE_PAGE (Button)
+ 0x19, 0x01, // USAGE_MINIMUM (Button 1)
+ 0x29, 0x0c, // USAGE_MAXIMUM (Button 12)
+ 0x15, 0x00, // LOGICAL_MINIMUM (0)
+ 0x25, 0x01, // LOGICAL_MAXIMUM (1)
+ 0x95, 0x0c, // REPORT_COUNT (12)
+ 0x75, 0x01, // REPORT_SIZE (1)
+ 0x81, 0x02, // INPUT (Data,Var,Abs)
+
+ 0x95, 0x01, // REPORT_COUNT (1) ; pad out the bits into a number divisible by 8
+ 0x75, 0x04, // REPORT_SIZE (4)
+ 0x81, 0x03, // INPUT (Const,Var,Abs)
+
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+ 0x09, 0x01, // USAGE (pointer)
+ 0xa1, 0x00, // COLLECTION (Physical)
+ 0x09, 0x30, // USAGE (X)
+ 0x09, 0x31, // USAGE (Y)
+ 0x15, 0xff, // LOGICAL_MINIMUM (-1)
+ 0x25, 0x01, // LOGICAL_MAXIMUM (1)
+ 0x95, 0x02, // REPORT_COUNT (2)
+ 0x75, 0x08, // REPORT_SIZE (8)
+ 0x81, 0x02, // INPUT (Data,Var,Abs)
+ 0xc0, // END_COLLECTION
+
+ 0xc0, // END_COLLECTION
+ 0xc0, // END_COLLECTION
+};
+
+Gamepad_::Gamepad_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1)
+{
+ epType[0] = EP_TYPE_INTERRUPT_IN;
+ PluggableUSB().plug(this);
+}
+
+int Gamepad_::getInterface(uint8_t* interfaceCount)
+{
+ *interfaceCount += 1; // uses 1
+ HIDDescriptor hidInterface = {
+ D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE),
+ D_HIDREPORT(sizeof(_hidReportDescriptor)),
+ D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01)
+ };
+ return USB_SendControl(0, &hidInterface, sizeof(hidInterface));
+}
+
+int Gamepad_::getDescriptor(USBSetup& setup)
+{
+ // Check if this is a HID Class Descriptor request
+ if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; }
+ if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; }
+
+ // In a HID Class Descriptor wIndex cointains the interface number
+ if (setup.wIndex != pluggedInterface) { return 0; }
+
+ // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol
+ // due to the USB specs, but Windows and Linux just assumes its in report mode.
+ protocol = HID_REPORT_PROTOCOL;
+
+ return USB_SendControl(TRANSFER_PGM, _hidReportDescriptor, sizeof(_hidReportDescriptor));
+}
+
+bool Gamepad_::setup(USBSetup& setup)
+{
+ if (pluggedInterface != setup.wIndex) {
+ return false;
+ }
+
+ uint8_t request = setup.bRequest;
+ uint8_t requestType = setup.bmRequestType;
+
+ if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE)
+ {
+ if (request == HID_GET_REPORT) {
+ // TODO: HID_GetReport();
+ return true;
+ }
+ if (request == HID_GET_PROTOCOL) {
+ // TODO: Send8(protocol);
+ return true;
+ }
+ }
+
+ if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE)
+ {
+ if (request == HID_SET_PROTOCOL) {
+ protocol = setup.wValueL;
+ return true;
+ }
+ if (request == HID_SET_IDLE) {
+ idle = setup.wValueL;
+ return true;
+ }
+ if (request == HID_SET_REPORT)
+ {
+ }
+ }
+
+ return false;
+}
+
+void Gamepad_::reset()
+{
+ _GamepadReport.X = 0;
+ _GamepadReport.Y = 0;
+ _GamepadReport.buttons = 0;
+ this->send();
+}
+
+void Gamepad_::send()
+{
+ USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &_GamepadReport, sizeof(GamepadReport));
+}
+
+uint8_t Gamepad_::getShortName(char *name)
+{
+ if(!next)
+ {
+ strcpy(name, gp_serial);
+ return strlen(name);
+ }
+ return 0;
+}
diff --git a/PSXControllerUSB/Gamepad.h b/PSXControllerUSB/Gamepad.h
new file mode 100644
index 0000000..9009a65
--- /dev/null
+++ b/PSXControllerUSB/Gamepad.h
@@ -0,0 +1,60 @@
+/* Gamepad.h
+ *
+ * Based on the advanced HID library for Arduino:
+ * https://github.com/NicoHood/HID
+ * Copyright (c) 2014-2015 NicoHood
+ *
+ * Copyright (c) 2021 Hendrik Osterholz
+ *
+ * GNU GENERAL PUBLIC LICENSE
+ * Version 3, 29 June 2007
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#pragma once
+
+#include "HID.h"
+
+extern const char* gp_serial;
+
+typedef struct {
+ uint16_t buttons;
+ int8_t X;
+ int8_t Y;
+} GamepadReport;
+
+
+class Gamepad_ : public PluggableUSBModule
+{
+ private:
+ uint8_t reportId;
+
+ protected:
+ int getInterface(uint8_t* interfaceCount);
+ int getDescriptor(USBSetup& setup);
+ uint8_t getShortName(char *name);
+ bool setup(USBSetup& setup);
+
+ uint8_t epType[1];
+ uint8_t protocol;
+ uint8_t idle;
+
+ public:
+ GamepadReport _GamepadReport;
+ Gamepad_(void);
+ void reset(void);
+ void send();
+};
diff --git a/PSXControllerUSB/PSXControllerUSB.ino b/PSXControllerUSB/PSXControllerUSB.ino
new file mode 100644
index 0000000..a8c7ba5
--- /dev/null
+++ b/PSXControllerUSB/PSXControllerUSB.ino
@@ -0,0 +1,99 @@
+/* DaemonBite PSX USB Adapter
+ * Author: Hendrik Osterholz
+ *
+ * Copyright (c) 2021 Hendrik Osterholz
+ *
+ * GNU GENERAL PUBLIC LICENSE
+ * Version 3, 29 June 2007
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#include "Gamepad.h"
+
+#define GAMEPAD_COUNT 1 // Set to 1 or 2 depending if you want to make a 1 or 2 port adapter
+#define GAMEPAD_COUNT_MAX 4
+
+// ATT: 20 chars max (including NULL at the end) according to Arduino source code.
+// Additionally serial number is used to differentiate arduino projects to have different button maps!
+const char *gp_serial = "PSX to USB";
+
+#include "Psx.h"
+
+#define dataPin 18
+#define cmndPin 2
+#define attPin 3
+#define clockPin 4
+
+/* -------------------------------------------------------------------------
+PSX controller socket (looking face-on at the front of the socket):
+_________________________
+| 9 8 7 | 6 5 4 | 3 2 1 |
+\_______________________/
+
+PSX controller plug (looking face-on at the front of the controller plug):
+_________________________
+| 1 2 3 | 4 5 6 | 7 8 9 |
+\_______________________/
+
+PSX Arduino Pro Micro
+--------------------------------------
+1 DATA A0 PF7
+2 CMD 2 PD1
+3 +7.6V
+4 GND GND
+5 VCC VCC
+6 ATT 3 PD0
+7 CLK 4 PD4
+8 N/C
+9 ACK
+
+------------------------------------------------------------------------- */
+
+Psx Psx;
+
+// Set up USB HID gamepads
+Gamepad_ Gamepad[GAMEPAD_COUNT];
+
+// Controllers
+uint16_t buttons[GAMEPAD_COUNT_MAX] = {0,0,0,0};
+uint16_t buttonsPrev[GAMEPAD_COUNT_MAX] = {0,0,0,0};
+uint8_t gp = 0;
+
+void setup()
+{
+ Psx.setupPins(dataPin, cmndPin, attPin, clockPin, 10);
+}
+
+void loop() { while(1)
+{
+ // Send data to USB if values have changed
+ for(gp=0; gp> 4;
+ Gamepad[gp]._GamepadReport.Y = ((buttons[gp] & psxDown) >> 1) - ((buttons[gp] & psxUp) >> 3);
+ Gamepad[gp]._GamepadReport.X = ((buttons[gp] & psxRight) >> 2) - (buttons[gp] & psxLeft);
+ buttonsPrev[gp] = buttons[gp];
+ Gamepad[gp].send();
+ }
+ }
+
+}}
diff --git a/PSXControllerUSB/Psx.cpp b/PSXControllerUSB/Psx.cpp
new file mode 100644
index 0000000..22939da
--- /dev/null
+++ b/PSXControllerUSB/Psx.cpp
@@ -0,0 +1,97 @@
+/* PSX Controller Decoder Library (Psx.cpp)
+ Written by: Kevin Ahrendt June 22nd, 2008
+
+ Controller protocol implemented using Andrew J McCubbin's analysis.
+ http://www.gamesx.com/controldata/psxcont/psxcont.htm
+
+ Shift command is based on tutorial examples for ShiftIn and ShiftOut
+ functions both written by Carlyn Maw and Tom Igoe
+ http://www.arduino.cc/en/Tutorial/ShiftIn
+ http://www.arduino.cc/en/Tutorial/ShiftOut
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+#include "Psx.h"
+
+Psx::Psx()
+{
+}
+
+byte Psx::shift(byte _dataOut) // Does the actual shifting, both in and out simultaneously
+{
+ _temp = 0;
+ _dataIn = 0;
+
+ for (_i = 0; _i <= 7; _i++)
+ {
+
+
+ if ( _dataOut & (1 << _i) ) digitalWrite(_cmndPin, HIGH); // Writes out the _dataOut bits
+ else digitalWrite(_cmndPin, LOW);
+
+ digitalWrite(_clockPin, LOW);
+
+ delayMicroseconds(_delay);
+
+ _temp = digitalRead(_dataPin); // Reads the data pin
+ if (_temp)
+ {
+ _dataIn = _dataIn | (B10000000 >> _i); // Shifts the read data into _dataIn
+ }
+
+ digitalWrite(_clockPin, HIGH);
+ delayMicroseconds(_delay);
+ }
+ return _dataIn;
+}
+
+
+void Psx::setupPins(byte dataPin, byte cmndPin, byte attPin, byte clockPin, byte delay)
+{
+ pinMode(dataPin, INPUT);
+ digitalWrite(dataPin, HIGH); // Turn on internal pull-up
+ _dataPin = dataPin;
+
+ pinMode(cmndPin, OUTPUT);
+ _cmndPin = cmndPin;
+
+ pinMode(attPin, OUTPUT);
+ _attPin = attPin;
+ digitalWrite(_attPin, HIGH);
+
+ pinMode(clockPin, OUTPUT);
+ _clockPin = clockPin;
+ digitalWrite(_clockPin, HIGH);
+
+ _delay = delay;
+}
+
+
+unsigned int Psx::read()
+{
+ digitalWrite(_attPin, LOW);
+
+ shift(0x01);
+ shift(0x42);
+ shift(0xFF);
+
+ _data1 = ~shift(0xFF);
+ _data2 = ~shift(0xFF);
+
+ digitalWrite(_attPin, HIGH);
+
+ _dataOut = (_data2 << 8) | _data1;
+
+ return _dataOut;
+}
diff --git a/PSXControllerUSB/Psx.h b/PSXControllerUSB/Psx.h
new file mode 100644
index 0000000..6b7b99c
--- /dev/null
+++ b/PSXControllerUSB/Psx.h
@@ -0,0 +1,82 @@
+/* PSX Controller Decoder Library (Psx.h)
+ Written by: Kevin Ahrendt June 22nd, 2008
+
+ Controller protocol implemented using Andrew J McCubbin's analysis.
+ http://www.gamesx.com/controldata/psxcont/psxcont.htm
+
+ Shift command is based on tutorial examples for ShiftIn and ShiftOut
+ functions both written by Carlyn Maw and Tom Igoe
+ http://www.arduino.cc/en/Tutorial/ShiftIn
+ http://www.arduino.cc/en/Tutorial/ShiftOut
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+
+#ifndef Psx_h
+#define Psx_h
+
+#include "Arduino.h"
+
+// Button Hex Representations:
+#define psxLeft 0x0001
+#define psxDown 0x0002
+#define psxRight 0x0004
+#define psxUp 0x0008
+#define psxStrt 0x0010
+#define psxSlct 0x0080
+
+#define psxSqu 0x0100
+#define psxX 0x0200
+#define psxO 0x0400
+#define psxTri 0x0800
+#define psxR1 0x1000
+#define psxL1 0x2000
+#define psxR2 0x4000
+#define psxL2 0x8000
+
+
+class Psx
+{
+ public:
+ Psx();
+ void setupPins(byte , byte , byte , byte , byte ); // (Data Pin #, CMND Pin #, ATT Pin #, CLK Pin #, Delay)
+ // Delay is how long the clock goes without changing state
+ // in Microseconds. It can be lowered to increase response,
+ // but if it is too low it may cause glitches and have some
+ // keys spill over with false-positives. A regular PSX controller
+ // works fine at 50 uSeconds.
+
+ unsigned int read(); // Returns the status of the button presses in an unsignd int.
+ // The value returned corresponds to each key as defined above.
+
+ private:
+ byte shift(byte _dataOut);
+
+ byte _dataPin;
+ byte _cmndPin;
+ byte _attPin;
+ byte _clockPin;
+
+ byte _delay;
+ byte _i;
+ boolean _temp;
+ byte _dataIn;
+
+ byte _data1;
+ byte _data2;
+ unsigned int _dataOut;
+};
+
+#endif
diff --git a/PSXControllerUSB/README.md b/PSXControllerUSB/README.md
new file mode 100644
index 0000000..2ee7da4
--- /dev/null
+++ b/PSXControllerUSB/README.md
@@ -0,0 +1,45 @@
+# DaemonBite PSX Controller To USB Adapter
+## Introduction
+This is a simple to build adapter for connecting PSX controllers to USB. Currently it supports normal digital PSX controllers, analog sticks are not supported.
+
+The input lag for this adapter is minimal (about 0.75ms average connected to MiSTer).
+
+## Parts you need
+- Arduino Pro Micro (ATMega32U4)
+- Male end of a PSX controller extension cable
+- Heat shrink tube (Ø ~20mm)
+- Micro USB cable
+
+## Wiring
+PSX controller socket (looking face-on at the front of the socket):
+```
+_________________________
+| 9 8 7 | 6 5 4 | 3 2 1 |
+\_______________________/
+```
+
+PSX controller plug (looking face-on at the front of the controller plug):
+```
+_________________________
+| 1 2 3 | 4 5 6 | 7 8 9 |
+\_______________________/
+```
+
+| PSX | Arduino Pro Micro |
+| ------ | ------ |
+| 1 DATA | A0 PF7 |
+| 2 CMD | 2 PD1 |
+| 3 +7.6V ||
+| 4 GND | GND |
+| 5 VCC | VCC |
+| 6 ATT | 3 PD0 |
+| 7 CLK | 4 PD4 |
+| 8 N/C ||
+| 9 ACK ||
+
+
+## License
+This project is licensed under the GNU General Public License v3.0.
+
+## Credits
+PSX Library from Arduino Playground: https://playground.arduino.cc/Main/PSXLibrary/
\ No newline at end of file