Dependencies:   mbed

main.cpp

Committer:
vcazan
Date:
2009-11-22
Revision:
0:eb315142ac34

File content as of revision 0:eb315142ac34:

#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();
    }
}