Simon Ford
/
PlayStationController
Diff: main.cpp
- Revision:
- 1:e4af215fb689
- Parent:
- 0:da9d848449ef
- Child:
- 2:e3dd9a5cefa0
diff -r da9d848449ef -r e4af215fb689 main.cpp --- a/main.cpp Sun Nov 22 11:10:42 2009 +0000 +++ b/main.cpp Sun Nov 22 18:31:52 2009 +0000 @@ -1,211 +1,51 @@ #include "mbed.h" -DigitalOut PSclock(p21); -DigitalIn PSdata(p22); -DigitalIn PSack(p23); -DigitalOut PScommand(p24); -DigitalOut PSattention(p25); +SPI spi(p24, p22, p21); // mosi, miso, sclk (or "command", "data", "clock") +DigitalOut cs(p25); // chip select (or "attention") -Serial pc(USBTX, USBRX); // tx, rx -int temp, data0, data1, data2, data3, data4, data5, i ,debounceSelect; +// setup the controller in to analog mode +void ps2_analog_mode() { + const char enter_config_mode[5] = {0x01, 0x43, 0x00, 0x01, 0x00}; + const char enable_analog_mode[9] = {0x01, 0x44, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00}; + const char exit_config_mode[9] = {0x01, 0x43, 0x00, 0x00, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A}; -// enable interupts - -int _BV(int bit) { - return 1 << bit; -} + cs = 0; + for (int i=0; i<5; i++) { + spi.write(enter_config_mode[i]); + } + cs = 1; -// PSx controller communication function. -// send a byte on the command line and receive one on the data line. -// needs Attention pin to have gone low before called to activate controller. -char gameByte (char command) { - wait(0.000001); - char data = 0x00; // clear data variable to save setting low bits later. - for(int i=0; i<8; i++) { - if (command & _BV(i)) { - PScommand=1; // bit bang "command" out on PScommand wire. - } else { - PScommand = 0; - } - PSclock = 0; // CLOCK LOW - wait_us(20); // wait for output to stabilise - //if ((PIND & _BV(PSdata)))_SFR_BYTE(data) |= _BV(i); // read PSdata pin and store - //else cbi(data, i); - PSclock = 1; // CLOCK HIGH + wait_us(1); + + cs = 0; + for (int i=0; i<9; i++) { + spi.write(enable_analog_mode[i]); } - PScommand = 1; + cs = 1; + + wait_us(1); - wait(0.00002); // wait for ACK to pass. - - return data; + cs = 0; + for (int i=0; i<9; i++) { + spi.write(exit_config_mode[i]); + } + cs = 1; } - -//sei(); - -// this loop continues to put PSx controller into analouge mode untill the -// controller responds with 0x73 in the 2nd byte. -// (PS2 controller responds with 0x73 when in analouge mode.) -// the status LEDs will continue to count upwards untill a controller is found. -// if everything is working correctly this should happen on the first pass of -// this loop but occasionally errors occur and a 2nd or 3rd itteration happen. -int chk_ana = 0, cnt = 0; - -void startup() { - - while (chk_ana != 0x73) { - // put controller in config mode - PScommand = 1; - PSclock = 1; - PSattention =0; - - gameByte(0x01); - gameByte(0x43); - gameByte(0x00); - gameByte(0x01); - gameByte(0x00); +int main() { + ps2_analog_mode(); - PScommand = 1; - wait(0.000001); - PSattention=1; - - wait(0.00001); - - // put controller in analog mode - PScommand = 1; - PSclock =1; - PSattention =1;; - - gameByte(0x01); - gameByte(0x44); - gameByte(0x00); - gameByte(0x01); - gameByte(0x03); - gameByte(0x00); - gameByte(0x00); - gameByte(0x00); - gameByte(0x00); - - PScommand = 1; - wait(0.000001); - PSattention =1; + while (1) { + const char poll_command[9] = {0x01, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + char response[9]; - wait(0.00001); - - // exit config mode - PScommand = 1; - PSclock = 1; - PSattention = 1; - - gameByte(0x01); - gameByte(0x43); - gameByte(0x00); - gameByte(0x00); - gameByte(0x5A); - gameByte(0x5A); - gameByte(0x5A); - gameByte(0x5A); - gameByte(0x5A); - - PScommand = 1; - wait(0.000001); - PSattention = 1; - - wait(0.00001); + cs = 0; + for (int i=0; i<9; i++) { + response[i] = spi.write(poll_command[i]); + } + cs = 1; - // poll controller and check in analouge mode. - PScommand = 1; - PSclock=1; - PSattention=0; - - 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); - - PScommand = 1; - wait(1); - PSattention =1; - - wait(0.00001); - - - // keep increasing counter to be dispalyed untill PSx controller confirms it's in analouge mode. - pc.putc(cnt++); - if (cnt > 254) { - cnt=0; - } + printf("Digital %02X %02X Analog %02X %02X %02X %02X\n", response[3], response[4], response[5], response[6], response[7], response[8]); } } - -// main program loop: -void loop () { - - PScommand=1; - PSclock=1; - PSattention = 0; - - 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. - - wait(0.000001); - PScommand = 1; // close communication with PSx controller - wait(0.000001); - PSattention = 1; // all done. - - - - if (!(data0 & _BV(0)) && !debounceSelect) { // capture one unique press of the "select" button - debounceSelect = 1; - } else if ((data0 & _BV(0)) && debounceSelect) { - if (i++ >= 5) i=0; - debounceSelect = 0; - } - - - // this switch decides which data register to show on status LEDs depending on how many times - // the "select" button on the PS2 controller has been pressed. - switch (i) { - case 0: - pc.printf("case 0: %d\n", data0); - break; - case 1: - pc.printf("case 1: %d\n", data1); - break; - case 2: - pc.printf("case 2: %d\n", data2); - break; - case 3: - pc.printf("case 3: %d\n", data3); - break; - case 4: - pc.printf("case 4: %d\n", data4); - break; - case 5: - pc.printf("case 5: %d\n", data5); - } - - -} //void loop - - -int main() { - startup(); - while(1) { - loop(); - } -}