|
Out of Stock? We've received a lot of emails asking about out of stock items, and sad to say, but CI is downsizing to a much smaller product offering. All of our guides, schematics and blog entries will stay available forever. Our new project is VMeter--a USB MIDI Controller Touch Strip & Display. |
Intro: There are all sorts of guides that explain how to interface a PS2 controller already out there. The goal here is to consolidate the information and make it as fast as possible to get up and running. Please let us know about mistakes!
Update: Check out the arduino ps2 library that Bill Porter helped polish.
Contents:
Wire Colors and Functionality: There are 9 wires, 6 wires are needed at a minimum to talk to the controller: (clock, data, command, power & ground, attention). To operate vibration motors, motor_power is also needed.
The play station sends a byte at the same time as it receives one (full duplex) via serial communication. The following pictures show actual signals between a playstation and guitar hero controller configured in analog mode (wammy bar sends back 7-bit value (0x7f - 0x00)).
The clock is held high until a byte is to be sent. It then drops low (active low) to start 8 cylces during which data is simultaneously sent and received. When the clock edge drops low, the values on the line start to change. When the clock goes from low to high, value are actually read. Bytes are transferred LSB (least significant bit) first, so the bits on the left (earlier in time) are less significant.
|
|
Scope shots showing the acknowledge and attention lines.
Much of this section is sourced from Dowty's consolidation and home-brew port sniffer and emulator.
Packets have a three byte header followed by an additional 2, 6 or 18 bytes of additional command and controller data (like button states, vibration motor commands, button pressures, etc.).
Controller defaults to digital mode and only transmits the on / off status of the buttons in the 4th and 5th byte. No joystick data, pressure or vibration control capabilities.
(no buttons pressed)
| byte # | 1 | 2 | 3 | 4 | 5 |
| Command | 0x01 | 0x42 | 0x00 | 0x00 | 0x00 |
| Data | 0xFF | 0x41 | 0x5A | 0xFF | 0xFF |
| byte # | source / type |
example value |
explanation |
| 1st byte | Command | 0x01 | New packets always start with 0x01 ... 0x81 for memory card? |
| Data | 0xFF | always 0xFF | |
| 2nd byte | Command | 0x42 | Main command: can either poll controller or configure it. See below for command listing |
| Data | 0x41 | Device Mode: the high nibble (4) indicates the mode (0x4 is digital, 0x7 is analog, 0xF config / escape?), (lynxmotion calls 0xF 'DS Native Mode'... not sure) the lower nibble (1) is how many 16 bit words follow the header, although the playstation doesn't always wait for all these bytes |
|
| 3rd byte | Command | 0x00 | Always 0x00 |
| Data | 0x5A | Always 0x5A, this value appears in several non-functional places |
| 4th byte | Command | 0x00 | Can be configured to control either of the motors |
| Data | 0xFF | Each digital (on/off) button state is mapped to one of the bits in the 4th and 5th byte | |
| 5th byte | Command | 0x00 | Can be configured to control either of the motors |
| Data | 0xFF | 1, or all 1's (0xFF) means everything is unpressed. |
| button | Select | L3 (jush push) | R3 | Start | Up | Right | Down | Left | L2 | R2 | L1 | R1 | Triangle | O | X | Square |
| byte.bit | 4.0 | 4.1 | 4.2 | 4.3 | 4.4 | 4.5 | 4.6 | 4.7 | 5.0 | 5.1 | 5.2 | 5.3 | 5.4 | 5.5 | 5.6 | 5.7 |
For example:
| button | Green | Red | Yellow | Blue | Orange | Up | Down | Select | Start | Wammy |
| byte.bit | 5.1 | 5.5 | 5.4 | 5.6 | 5.7 | 4.4 | 4.6 | 4.0 | 4.3 | byte 9: 0x7f (released) to 0x00 (pressed) |
The most comprehensive listings that we've found are Dowty's and lynxmotion's. This listing is based on information from both that has been tested.
The controller can be configured (through command 0x4F) to respond with more or less information about each button with each poll. Only works when the controller is already in configuration mode (0xF3)... use Command 0x43 to enter / exit configuration mode.
| byte # | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| Command | 0x01 | 0x41 | 0x00 | 0x5A | 0x5A | 0x5A | 0x5A | 0x5A | 0x5A |
| Data | 0xFF | 0x41 | 0x5A | 0xFF | 0xFF | 0x03 | 0x00 | 0x00 | 0x5A |
| section | header | bits corresponding to buttons in response packet | |||||||
Depending on the controller's configuration, this command can get all the digital and analog button states, as well as control the vibration motors.
| byte # | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| Command (hex) | 01 | 42 | 00 | WW | YY | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
| Data (hex) | FF | 79 | 5A | FF | FF | 7F | 7F | 7F | 7F | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
| section | header | digital | analog joy | button pressures (0xFF = fully pressed) | |||||||||||||||||
| analog map | RX | RY | LX | LY | R | L | U | D | Tri | O | X | Sqr | L1 | R1 | L2 | R2 | |||||
This can poll the controller like 0x42, but if the first command byte is 1, it has the effect of entering config mode (0xF3), in which the packet response can be configured. If the current mode is 0x41, this command only needs to be 5 bytes long. Once in config / escape mode, 0x43 does not return button states anymore, but 0x42 still does (except for pressures). Also, all packets have will 6 bytes of command / data after the header.
| byte # | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| Command (hex) | 01 | 43 | 00 | 0x01 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
| Data (hex) | FF | 79 | 5A | FF | FF | 7F | 7F | 7F | 7F | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
| section | header | digital | analog joy | button pressures (0xFF = fully pressed) | |||||||||||||||||
| analog map | RX | RY | LX | LY | R | L | U | D | Tri | O | X | Sqr | L1 | R1 | L2 | R2 | |||||
Only works after the controller is in config mode (0xF3).
| byte # | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| Command (hex) | 01 | 44 | 00 | 0x01 | 0x03 | 00 | 00 | 00 | 00 |
| Data (hex) | FF | F3 | 5A | 00 | 00 | 00 | 00 | 00 | 00 |
| section | header | config parameters | |||||||
Only works after the controller is in config mode (0xF3).
| byte # | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| Command (hex) | 01 | 45 | 00 | 5A | 5A | 5A | 5A | 5A | 5A |
| Data (hex) | FF | F3 | 5A | 03 | 02 | 01 | 02 | 01 | 00 |
| section | header | config parameters | |||||||
This command is always issued twice in a row, and appears to be retrieving a 10 byte constant of over those two calls. It is always called in a sequence of 0x46 0x46 0x47 0x4C 0x4C. Only works after the controller is in config mode (0xF3).
| byte # | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| Command (hex) | 01 | 46 | 00 | 00 | 5A | 5A | A | 5A | 5A |
| Data (hex) | FF | F3 | 5A | 00 | 00 | 00 | 02 | 00 | 0A |
| section | header | config parameters | |||||||
| byte # | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| Command (hex) | 01 | 46 | 00 | 01 | 5A | 5A | A | 5A | 5A |
| Data (hex) | FF | F3 | 5A | 00 | 00 | 00 | 00 | 00 | 14 |
| section | header | config parameters | |||||||
It is always called in a command sequence of 0x46 0x46 0x47 0x4C 0x4C. Only works after the controller is in config mode (0xF3).
| byte # | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| Command (hex) | 01 | 47 | 00 | 00 | 5A | 5A | A | 5A | 5A |
| Data (hex) | FF | F3 | 5A | 00 | 00 | 02 | 00 | 00 | 00 |
| section | header | config parameters | |||||||
This command is always issued twice in a row, and appears to be retrieving a 10 byte constant of over those two calls. It is always called in a command sequence of 0x46 0x46 0x47 0x4C 0x4C. Only works after the controller is in config mode (0xF3).
| byte # | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| Command (hex) | 01 | 4C | 00 | 00 | 5A | 5A | A | 5A | 5A |
| Data (hex) | FF | F3 | 5A | 00 | 00 | 00 | 04 | 00 | 00 |
| section | header | config parameters | |||||||
| byte # | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| Command (hex) | 01 | 4C | 00 | 01 | 5A | 5A | A | 5A | 5A |
| Data (hex) | FF | F3 | 5A | 00 | 00 | 00 | 06 | 00 | 00 |
| section | header | config parameters | |||||||
Only works after the controller is in config mode (0xF3).
| byte # | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| Command (hex) | 01 | 4D | 00 | 00 | 01 | FF | FF | FF | FF |
| Data (hex) | FF | F3 | 5A | 00 | 01 | FF | FF | FF | FF |
| section | header | config parameters | |||||||
This could set up the controller to only reply with the L1 and R1 pressures for instance. Only works after the controller is in config mode (0xF3).
| byte # | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| Command (hex) | 01 | 4F | 00 | FF | FF | 03 | 00 | 00 | 00 |
| Data (hex) | FF | F3 | 5A | 00 | 00 | 00 | 00 | 00 | 5A |
| section | header | config parameters | |||||||
The following sequence will setup a controller to send back all available analog values, and also map the left and right motors to command bytes 4 and 5.
| byte # | 1 | 2 | 3 | 4 | 5 |
| Command (hex) | 01 | 42 | 00 | FF | FF |
| Data (hex) | FF | 41 | 5A | FF | FF |
| section | header | digital | |||
| byte # | 1 | 2 | 3 | 4 | 5 |
| Command (hex) | 01 | 43 | 00 | 0x01 | 00 |
| Data (hex) | FF | 41 | 5A | FF | FF |
| section | header | digital | |||
| byte # | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| Command (hex) | 01 | 44 | 00 | 0x01 | 0x03 | 00 | 00 | 00 | 00 |
| Data (hex) | FF | F3 | 5A | 00 | 00 | 00 | 00 | 00 | 00 |
| section | header | config parameters | |||||||
| byte # | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| Command (hex) | 01 | 4D | 00 | 00 | 01 | FF | FF | FF | FF |
| Data (hex) | FF | F3 | 5A | 00 | 01 | FF | FF | FF | FF |
| section | header | config parameters | |||||||
| byte # | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| Command (hex) | 01 | 4F | 00 | FF | FF | 03 | 00 | 00 | 00 |
| Data (hex) | FF | F3 | 5A | 00 | 00 | 00 | 00 | 00 | 5A |
| section | header | config parameters | |||||||
| byte # | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| Command (hex) | 01 | 43 | 00 | 0x00 | 5A | 5A | 5A | 5A | 5A |
| Data (hex) | FF | F3 | 5A | 00 | 00 | 00 | 00 | 00 | 00 |
| section | header | config parameters | |||||||
| byte # | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| Command (hex) | 01 | 42 | 00 | WW | YY | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
| Data (hex) | FF | 79 | 5A | FF | FF | 7F | 7F | 7F | 7F | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
| section | header | digital | analog joy | button pressures (0xFF = fully pressed) | |||||||||||||||||
| analog map | RX | RY | LX | LY | R | L | U | D | Tri | O | X | Sqr | L1 | R1 | L2 | R2 | |||||
This excel sheet lists both the commands and response data between a play station and various controllers when the controller is first plugged in. Includes guitar hero, dual shock, wire less katana and chinese knock-off (looks the same as the dual shock).
Both a guitar hero game and dirt-bike game (to get vibration motor control data) were used.
We used 2 PIC18f4550 to do the port sniffing, see below to download the code.
The first program will configure a controller in analog mode so that all the joysticks and button pressures can be read. It also sets up the Left pressure to controller the left vibration motor and the Right button pressure to toggle the smaller right vibration motor.
Each command and response packet is sent out a serial port at 57600 kbs.
The second program can operate in two modes:
Connection Schematic:
note: avoid connecting the PIC's SPI clock to a play station's clock when the PIC is configured as a SPI master.