I am trying to read a Playstation controller with an Orangutan X2. I’ve spent a bit of time familiarizing myself with the protocol, which I think I have a pretty good feel for, but my code doesn’t work. Any help would be greatly appreciated!! Thanks, code is below.
//defines pins and constants
#define PS2_DATA PA0 //data
#define PS2_CMD PA1 //command
#define PS2_ATT PA2 //attention
#define PS2_CLK PA3 //clock
#define PS2_ACK PA4 //acknowledge
#define PS2_START_CMD 0x01
#define PS2_REQUEST_DATA 0x42
#define PS2_NO_CMD 0x00
//function prototypes
void PS2Init(void);
void PS2Get(void);
unsigned char PS2ReadSend(unsigned char command);
//variables
unsigned char PS2TEMP;
unsigned char PS2ID;
unsigned char PS2CMD1;
unsigned char PS2CMD2;
//function definitions
void PS2Init(void) //initiate, must be called first
{
DDRA |= (1<<PS2_CLK)|(1<<PS2_ATT)|(1<<PS2_CMD); //set pins as outputs
PORTA |= (1<<PS2_CLK)|(1<<PS2_ATT); //start clock, attention, acknowledge high
} //END PS2Init()
void PS2Get(void)
{
PORTA &= ~(1<<PS2_ATT); //pull attention low
PS2TEMP = PS2ReadSend(PS2_START_CMD);
while(((PINA)&(1<<PS2_ACK))); //wait for acknoledge to be pulled low
PS2ID = PS2ReadSend(PS2_REQUEST_DATA);
while(((PINA)&(1<<PS2_ACK))); //wait for acknoledge to be pulled low
PS2TEMP = PS2ReadSend(PS2_NO_CMD);
while(((PINA)&(1<<PS2_ACK))); //wait for acknoledge to be pulled low
PS2CMD1 = PS2ReadSend(PS2_NO_CMD);
while(((PINA)&(1<<PS2_ACK))); //wait for acknoledge to be pulled low
PS2CMD2 = PS2ReadSend(PS2_NO_CMD);
PORTA |= (1<<PS2_CLK); //clock high
PORTA |= (1<<PS2_ATT); //attention high
} //END PS2Get()
unsigned char PS2ReadSend(unsigned char command) //clock must be high before calling
{
unsigned char PS2Data = 0x00;
for(int i=0;i<8;i++)
{
PORTA &= ~(1<<PS2_CLK); //set clock low
if(((command)&(1<<i))) //is PS2 command bit i set?
PORTA |= (1<<PS2_CMD); //if yes set PS2_CMD bit
else //
PORTA &= ~(1<<PS2_CMD); //if no clear PS2_CMD bit
_delay_us(100); //delay 100us
PORTA |= (1<<PS2_CLK); //set clock high
if(((PINA)&(1<<PS2_DATA))) //is PS2_DATA bit set?
PS2Data |= (1<<i); //if yes set PS2Data bit i
else //
PS2Data &= ~(1<<i); //if no clear PS2Data bit i
_delay_us(100); //delay 100us
}
return PS2Data;
} //END PS2ReadSend()
Before looking at your code in too much detail, can you be more specific about how it doesn’t work? Have you made any partial progress at all at detecting what the Play Station controller is sending you? Since I don’t know anything about the Play Station controller protocol, it will be difficult to debug your program without some hints about where to look.
I haven’t been able to get any response from the playstation controller. The data transfer protocol is represented by this picture
There is a bi-directional data transfer (command is to the controller, data is from the controller). First, the ATT (attention) line is pulled low by the playstation (or my microcontroller). The clock starts on high, when it goes low, the command line and data lines are loaded with data their values. When the clock goes high, the command line and data line are read by the controller and playstation, respectively. Again the clock goes low and the next bit is set on the command and data lines. After the last bit of the byte is transferred, the controller pulls the ACK (acknowledge) low to signal it received the information.
The playstation first sends the command value 0x01 to the controller. The ps then sends 0x42 while the controller sends its configuration (digital or analog). Then the ps controller sends 0x5A (which means nothing) while the ps is idle. Then the controller sends two bytes which contain the status of all the buttons (in digital mode).
This flow chart is what the software is trying to accomplish (note that the controller does not acknowledge the last byte)
Yeah I’ve double and tripple checked my pins. Yes I’ve connected to the 5V source on the OX2, and I know it has power since I can turn on the analog light. The only thing I haven’t done is connect the pin that needs 7.2V, but that line is supposed to be just for the shock motors and shouldn’t be needed for what I’m trying to do.
I figured it out, and like I suspected, it was a ridiculously simple fix. I was reading on many sites about the ps protocol, and only that I just found said the controller needed a pull up resistor on the data pin. So all I needed was to add
|(1<<PS2_DATA) at the end of my PORTA register and it works perfectly. Thank you anyway for your willingness to help.