Skinny Satan

A cool Nerd To Hangout With

Interface Playstation Joystick to AVR Microcontroller

atmega16 PS2 Interface

First thing while making any Electronic Device we should consider is its controlling box should be classy. Let it be a Dark Green text Batch file or a Mad scientist Tube light Switch. In this Article we will show you how to interface the playstation Joystick to any other Microcontroller and use it for your purpose.

A playstation Joystick has total 9 pins which are.

1 DAT Data
2 CMD Command
3 N/C Vibrations
4 GND Ground
5 VCC Power
6 ATT Attention
7 CLK Clock
8 N/C Unknown
9 ACK Acknowledge

From this we can see that the Joystick can be made to work on the SPI protocol.

Atmega uC does have its own SPI but we will do it only by bitbanging.

main.c

#include<avr/io.h>
#include<util/delay.h>
#include"LCD.h"
#include"joystick.h"

void main()
{

lcd_init();
ps2_init();

joystick_config();
joystick_config();
joystick_config();//more than once Required to Put it in RED mode If called once Analog is to be set
lcd_string("RED");

while(1)
{
joystick_poll();

lcd_gotoxy2(0);
lcd_showvalue(data0);
lcd_gotoxy2(8);
lcd_showvalue(data1);
lcd_gotoxy1(0);
lcd_showvalue(data2);
lcd_gotoxy1(4);
lcd_showvalue(data3);
lcd_gotoxy1(9);
lcd_showvalue(data4);
lcd_gotoxy1(13);
lcd_showvalue(data5);

}
}

joystick.h

#define PSclock            2               // PD2
#define PSdata             3               // PD3
#define PSacknolage  4               // PD4
#define PScommand   5               // PD5
#define PSattention     6               // PD6

unsigned char chk_ana = 0;
int data0=0,data1=0,data2=0,data3=0,data4=0,data5=0,temp=0;

int gameByte(int command)
{
        int i ;
        _delay_us(1);
        int data = 0x00;                             // clear data variable to save setting low bits later.
        for(i=0;i<8;i++)
        {
                if(command & _BV(i)) 
                {
                PORTD|=(1<<PScommand);//sbi(PORTD, PScommand);
                }// bit bang "command" out on PScommand wire.
                else
                {
                PORTD&=~(1<<PScommand);
                }
                PORTD&=~(1<<PSclock);                             // CLOCK LOW
                _delay_us(1);                                              // wait for output to stabilise
                if((PIND & _BV(PSdata)))
                {
                    data|=(1<<i);  // read PSdata pin and store
                }//else cbi(data, i);
                PORTD|=(1<<PSclock);                             // CLOCK HIGH
        }
        PORTD|=(1<<PScommand);

        _delay_us(20);                                                   // wait for ACK to pass.

        return(data);
}

void joystick_config()
{
     // put controller in config mode
       PORTD|=(1<<PScommand);
       PORTD|=(1<<PSclock);
       PORTD&=~(1<<PSattention);

       gameByte(0x01);
       gameByte(0x43);
       gameByte(0x00);
       gameByte(0x01);
       gameByte(0x00);

       PORTD|=(1<<PScommand);
       _delay_ms(1);
       PORTD|=(1<<PSattention);

       _delay_ms(10);

       // put controller in analouge mode
       PORTD|=(1<<PScommand);
       PORTD|=(1<<PSclock);
       PORTD&=~(1<<PSattention);

       gameByte(0x01);
       gameByte(0x44);
       gameByte(0x00);
       gameByte(0x01);
       gameByte(0x03);
       gameByte(0x00);
       gameByte(0x00);
       gameByte(0x00);
       gameByte(0x00);

       PORTD|=(1<<PScommand);
       _delay_ms(1);
       PORTD|=(1<<PSattention);

       _delay_ms(10);

       // exit config mode
       PORTD|=(1<<PScommand);
       PORTD|=(1<<PSclock);
       PORTD&=~(1<<PSattention);

       gameByte(0x01);
       gameByte(0x43);
       gameByte(0x00);
       gameByte(0x00);
       gameByte(0x5A);
       gameByte(0x5A);
       gameByte(0x5A);
       gameByte(0x5A);
       gameByte(0x5A);

       PORTD|=(1<<PScommand);
       _delay_ms(1);
       PORTD|=(1<<PSattention);

       _delay_ms(10);

       // poll controller and check in analouge mode.
       PORTD|=(1<<PScommand);
       PORTD|=(1<<PSclock);
       PORTD&=~(1<<PSattention);

       gameByte(0x01);
       chk_ana = gameByte(0x42);            // the 2nd byte to be returned from the controller should = 0x73 for "red" analouge controller.
       gameByte(0x00);
       gameByte(0x00);
       gameByte(0x00);
       gameByte(0x00);
       gameByte(0x00);
       gameByte(0x00);
       gameByte(0x00);

       PORTD|=(1<<PScommand);
       _delay_ms(1);
       PORTD|=(1<<PSattention);
       _delay_ms(10);

}

void ps2_init()
{
    DDRD|=(1<<PD2);                 // clock. output. (blue)

   DDRD&=~(1<<PD3);                 // data. input. (brown)
   PORTD|=(1<<PD3);               //    enable pullup resistor

   DDRD&=~(1<<PD4);                 // acknolage. input. (green)
   PORTD|=(1<<PD4);               //    enable pullup resistor

   DDRD|=(1<<PD5);                 // command. output. (orange)

   DDRD|=(1<<PD6);                 // attention. output. (yellow)
}

void joystick_poll()
{
        PORTD|=(1<<PScommand);                          // start communication with PSx controller
        PORTD|=(1<<PSclock);
        PORTD&=~(1<<PSattention);

        gameByte(0x01);                                       // bite 0. header.
        temp = gameByte(0x42);                          // bite 1. header. (should possibly put test on this byte to detect unplugging of controller.)
        gameByte(0x00);                                       // bite 2. header.

        data0 = gameByte(0x00);                         // bite 3. first data bite.
        data1 = gameByte(0x00);                         // bite 4.
        data2 = gameByte(0x00);                         // bite 5.
        data3 = gameByte(0x00);                         // bite 6.
        data4 = gameByte(0x00);                         // bite 7.
        data5 = gameByte(0x00);                         // bite 8.

        _delay_us(1);
        PORTD|=(1<<PScommand);                      // close communication with PSx controller
        _delay_us(1);
        PORTD|=(1<<PSattention);                        // all done.
}

How it works :
Hardware:The clk pin acts as a latch and while transmission we have to toggle it.
Then we only must transmit our data serially through CMD pin and receive data at DATA line.
As simple as that πŸ˜€
Code:
first when we call configuration the header file 0x43 tells it to produce Analog mode in Joystick and after we have configured after sending the header 0x01 and 0x42 we have to simply send the 0x00 and receive the data serially from Joystick.

Advertisements

6 comments on “Interface Playstation Joystick to AVR Microcontroller

  1. Anshul Mittal
    October 29, 2013

    Is it an Atmega32 microcontroller you’re using or is it something else? Either way, could you please specify the connections to the uC and also how do i rig it (as in what kinda code and what sorta connection) so as to enable me to use all the buttons and both the joysticks of the PS2 controller to control various motors/LEDs etc connected on some PORT of the uc?
    Please help!! Thanks in advance. πŸ™‚

  2. Anshul Mittal
    October 29, 2013

    Okay, My bad. I just noticed that you HAVE mentioned the connections in your code (except for ‘vibration’ and ‘unknown’, but i guess i won’t be needing them), but i still am not sure where will my outputs be reflected if it connect this gamepad and press the buttons or vary the position of the joystick. i.e. i’m unable to figure out how do i read the Input from the Buttons and the joystick so as to give a specific set of outputs.
    Looking forward to a positive reply. πŸ™‚

    • S4t4n
      November 2, 2013

      i wasnt interested in the vibrations and generally unknown is not connected. If u want to add vibrate you can turn it on through transistor only. Just put the VCC 7.2 only.

  3. Marek
    March 17, 2015

    Hi. What frequency are you running? Did you use any resistors?

  4. tsk0408
    September 27, 2015

    hi. are you using ATMega16 , can i email you my code for review thanks in advance

    • S4t4n
      October 12, 2015

      Yes Atmega16. You can mail it to me right away. Ill take a look.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: