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.
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. π
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. π
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.
Hi. What frequency are you running? Did you use any resistors?
hi. are you using ATMega16 , can i email you my code for review thanks in advance
Yes Atmega16. You can mail it to me right away. Ill take a look.