www.webx.dk Start page
MY little Radio Control page
MY little homemade electronics collection page
Sony Playstation gamepad joystick used to control robots or whatever

First you goto pinouts.ru and search for playstation, then you find this link:
http://pinouts.ru/data/playstation_9_pinout.shtml if this dont work, I have a local copy here.

That page have a few missing informations so I measured the signal timings on a good old Playstation one.
Clock pulse low=2uS Clock pulse high=2uS (works fine much faster)
Delay from byte to byte 17-35uS (works fine with 10uS)
Att select signal before clocking can start 17uS (works fine with 10uS)
Repeat time 20mS (works fine much faster if needed)
Data is sampled before the rising edge of clock, maybe it is the same as:
after the falling edge as written on other sites.
See the source: clock low, delay, sample, clock hi, repeat.

This is how I have timed the data sampling arcording to the clock pulse.
The commands works much faster, at pulses down to 0.7uS if you need the speed..

Here is the signals on an original PS one, using variable timebase, one div about 16uS:

See bigger version


Since the original playstation gamepads come with a funky special plug, I have just cut the wire and found out the collour codings,
I use a DB9 female at the gamepad cable, same pin numbers as the original plug offcourse.



The byte 4 and byte 5 from the controllers are the same, for old and new versions.
so no need to have special software if the analog values are not needed, here is the software I have used in my Atmel AVR controller,
Made using AVR Studio 4.12 and AVR Gcc 214. DOWNLOAD C and H files ZIPPED

  unsigned char i;
  unsigned char PS2byte;
  unsigned char PS2data4;
  unsigned char PS2data5;

#define PS2clk 3 // bit 3
#define PS2cmd 2 // bit 2
#define PS2att 1 // bit 1
#define PS2dat 0 // bit 0
#define PS2PORT PORTB // change to fit your port hardware
#define PS2IN PINB    // change to fit your port hardware

void ReadGamepad()
{
   SET(PS2PORT,PS2cmd); 
   SET(PS2PORT,PS2clk); 
   CLR(PS2PORT,PS2att); // low enable joystick

   Delay(1); // one uS delay CPU timed at the clock speed your AVR is running.
   PS2byte=0x01; // first command
   for(i=0;i<8;i++)
   {
      if(CHK(PS2byte,i)) SET(PS2PORT,PS2cmd);
      else CLR(PS2PORT,PS2cmd);
      CLR(PS2PORT,PS2clk); //Delay(1); if you run faster then 8Mhz you might need a small delay
      SET(PS2PORT,PS2clk); 
   }
   SET(PS2PORT,PS2cmd); 

   Delay(1);
   PS2byte=0x42; // sec command
   for(i=0;i<8;i++)
   {
      if(CHK(PS2byte,i)) SET(PS2PORT,PS2cmd);
      else CLR(PS2PORT,PS2cmd);
      CLR(PS2PORT,PS2clk); //Delay(1); if you run faster then 8Mhz you might need a small delay
      SET(PS2PORT,PS2clk); 
   }
   SET(PS2PORT,PS2cmd); 

   Delay(1);
   for(i=0;i<8;i++)  // 3 byte
   {
      CLR(PS2PORT,PS2cmd);
      CLR(PS2PORT,PS2clk); //Delay(1); if you run faster then 8Mhz you might need a small delay
      SET(PS2PORT,PS2clk); 
   }
   SET(PS2PORT,PS2cmd); 

   Delay(1);
   PS2data4=0;
   for(i=0;i<8;i++)  // 4 byte
   {
      CLR(PS2PORT,PS2cmd);
      CLR(PS2PORT,PS2clk); Delay(1); // this delay is needed even at 8MHz!!
      if(CHK(PS2IN,PS2dat)) SET(PS2data4,i); 
      SET(PS2PORT,PS2clk);
   }
   SET(PS2PORT,PS2cmd); 

   Delay(1);
   PS2data5=0;
   for(i=0;i<8;i++) // 5 byte
   {
      CLR(PS2PORT,PS2cmd);
      CLR(PS2PORT,PS2clk); Delay(1);  // this delay is needed even at 8MHz!!
      if(CHK(PS2IN,PS2dat)) SET(PS2data5,i);
      SET(PS2PORT,PS2clk);
   }
   SET(PS2PORT,PS2cmd); 
   Delay(1);
   SET(PS2PORT,PS2att); // HI disable joystick
}

So after running this sub routine (takes 410uS at 8MHz clock) the variables PS2data4 and PS2data5
will contain the bits from all the buttons.


All bits are active low, if nothing is pressed both bytes will be 0xFF

Here is an example of how to use the PS2data4 byte:

if (PS2data4==0xef)  // check if bit 4 is low
{
    directionNow=walkforw;
}
 

Made: 28th of December 2005 Thomas Scherrer - OZ2CPU - Denmark.