This is an Arduino library used to emulate a Playstation 1/2 controller, exclusively for the Leonardo / Micro / Pro Micro.
- This library will only function in digital mode. That means no joysticks and no pressure sensitive triggers or buttons.
It is highly recommended that you use an Arduino Micro or comparable clone. This is due to the fact that all necessary pins are easily broken out. Using a Leonardo or Pro Micro will require you to solder onto pre-existing LEDs, which can be difficult.
You will also need qty 1 (one) NPN signal transistor. I used 2N2222A, but many others will work. A similar N-Channel MOSFET, such as the 2N7000 will also work.
Lastly, you will need a cable to plug into your Playstation. Options include:
- Cutting the cord from an existing controller
- Buying an extension cable and using the male end
- A pre-terminated cable such as this one
Let's get acquainted with the Playstation cable and color codes. It is always a good idea to verify that these colors match the cable you own. Some third party or cheap cables may vary.
- CIPO: (Controller-In / Peripheral-Out) This is data from the controller to the console. It is held HIGH via a pull-up resistor inside the console. We will use the transistor to pull this line to GND. Also known as MISO.
- COPI: (Controller-Out / Peripheral-In) This is the data from the console to the controller. Also known as MOSI.
- 7.6V: This provides power for the rumble motors. See Powering the Arduino.
- GND: The common ground for the console, also known as 0V.
- 3.3V: This is power coming from the console, which typically powers the controller processor. See Powering the Arduino.
- CS: (Chip Select) This line goes LOW when the console is requesting data from a controller. This is how the console selects which player's controller to read from. Also known as SS.
- SCK: (Serial Clock) This is the clock signal coming from the console.
- N/C: This wire is not used (not connected).
- ACK: This is how the controller tells the console it has finished sending data. It is held HIGH via a pull-up resistor inside the console.
The example program follows the wiring below. Please refer to your specific transistor datasheet for its pinout.
- CIPO
- COPI
- CS
- SCK
- ACK
- VIN
- 5V
- GND
There's a few options you have for powering the arduino.
Connect 7.6V to VIN on the Arduino. This will power the Arduino off the rumble line and at 5V. It is safe to plug in the USB connector at the same time using this method.
Disconnect both 7.6V and 3.3V from the Arduino and only use the USB connection. USB will need to be plugged in any time you wish to use the controller.
Disconnect 7.6V and connect 3.3V from the Playstation to the 5V pin on your Arduino. This will force the chip to run at 3.3V.
DO NOT PLUG IN USB WHEN CONNECTED LIKE THIS as it can damage the Playstation or your PC.
- Download: https://github.com/veroxzik/arduino-psx-controller/archive/refs/heads/main.zip
- In the Arduino IDE, select
Sketch
>Include Library
>Add .ZIP Library...
. Browse to where the downloaded ZIP file is located and click Open. The example will now appear underFile
>Examples
>Arduino-PSX
.
Include the header at the top of your code. This will automatically create an instance of the PSX
object.
#include <arduino_psx.h>
Next, run the initialization function inside setup
:
void setup() {
PSX.init(8);
}
The init
function takes up to 3 arguments.
ackPin
: This is the pin that the ACK line is attached to. Use the digital pin number, shown in the diagram above as theD
numbers.- The default is
8
.
- The default is
invertACK
: This allows you to invert the logic for the ACK pin. Set this tofalse
when connected directly to the Arduino and usetrue
when connected via a transistor.- The default is
false
.
- The default is
invertCIPO
: This allows you to invert the logic for the CIPO pin. Set this tofalse
when connected directly to the Arduino and usetrue
when connected via a transistor. Please see Bypassing the Transistor- The default is
true
.
- The default is
For certain types of controllers (Pop'n Music and Guitar Hero come to mind), the game expects certain buttons to always be pressed.
To do so, run the method setAlwaysHeld
using the button enums BITWISE OR
'd together.
void setup() {
PSX.init(8);
PSX.setAlwaysHeld(PS_INPUT::PS_LEFT | PS_INPUT::PS_DOWN | PS_INPUT::PS_RIGHT);
}
Buttons can be set easily using the setButton
method.
Set a button to true
to press it and false
to release it.
// Press left button
PSX.setButton(PS_INPUT::PS_LEFT, true);
// Release left button
PSX.setButton(PS_INPUT::PS_LEFT, false);
Valid options are as follows:
PS_INPUT::PS_SELECT
PS_INPUT::PS_L3
PS_INPUT::PS_R3
PS_INPUT::PS_START
PS_INPUT::PS_UP
PS_INPUT::PS_RIGHT
PS_INPUT::PS_DOWN
PS_INPUT::PS_LEFT
PS_INPUT::PS_L2
PS_INPUT::PS_R2
PS_INPUT::PS_L1
PS_INPUT::PS_R1
PS_INPUT::PS_TRIANGLE
PS_INPUT::PS_CIRCLE
PS_INPUT::PS_CROSS
PS_INPUT::PS_SQUARE
A basic example is included. Navigate to the Example sketches in the Arduino IDE to run it.
The example includes D-Pad controls, as well as O and X. Connect the following pins to GND to press the corresponding button:
Pin | Button |
---|---|
A0 | LEFT |
A1 | DOWN |
A2 | UP |
A3 | RIGHT |
A4 | O |
A5 | X |
For safety and performance reasons, I suggest using the transistor as shown above to prevent backfeeding voltage into your console. This has the potential to cause harm.
It has been noted by myself and others that bypassing the use of a transistor on the CIPO line may result in poor performance or corrupted data. It is not a software issue, but a result of electrical characteristics related to the Arduino, the length and impedance of your wires, and other factors. I will not be able to troubleshoot your situation if you go this route.
Some code used from watterott's Arduino-Libs. Specific lines are noted.
Copyright (c) 2011-2020 Watterott electronic (www.watterott.com)
All rights reserved.
Wiring and protocol information from Curious Inventor's page on the Playstation Controller
Code base adapted from CrazyRedMachine's Ultimate Pop'n Controller, which itself is based on busslave's PSX_RECEIVER.cpp.
Discord User GoroKaneda for getting me to work on and document this, as well as additional testing.
Additional suggestions and feedback from progmem.
If you appreciate this library or the other projects I do, you can make a monetary donation below. Thanks!