Dependencies:   mbed

Revision:
0:eb315142ac34
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Nov 22 18:03:23 2009 +0000
@@ -0,0 +1,210 @@
+#include "mbed.h"
+
+DigitalOut PSclock(p21);
+DigitalIn PSdata(p22);
+DigitalIn PSack(p23);
+DigitalOut PScommand(p24);
+DigitalOut PSattention(p25);
+
+Serial pc(USBTX, USBRX); // tx, rx
+int temp, data0, data1, data2, data3, data4, data5, i ,debounceSelect;
+
+// enable interupts
+
+int _BV(int bit) {
+    return 1 << bit;
+}
+
+// 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_us(1);
+    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
+    }
+    PScommand = 1;
+
+    wait_us(20);                             // wait for ACK to pass.
+
+    return data;
+}
+
+
+//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);
+
+        PScommand = 1;
+        wait_ms(1);
+        PSattention=1;
+
+        wait_ms(10);
+
+        // 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_ms(1);
+        PSattention =1;
+
+        wait_ms(10);
+
+        // 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_ms(1);
+        PSattention = 1;
+
+        wait_ms(10);
+        // 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_ms(1);
+        PSattention =1;
+
+        wait_ms(10);
+
+
+        // keep increasing counter to be dispalyed untill PSx controller confirms it's in analouge mode.
+        pc.putc(cnt++);
+        if (cnt > 254) {
+            cnt=0;
+        }
+    }
+}
+
+
+// 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_ms(1);
+    PScommand = 1;                      // close communication with PSx controller
+    wait_ms(1);
+    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);
+    }
+
+    pc.printf("$d\n",data1);
+} //void loop
+
+
+int main() {
+    startup();
+    while (1) {
+        loop();
+    }
+}