Vlad Cazan
/
PlayStationController
main.cpp@0:eb315142ac34, 2009-11-22 (annotated)
- Committer:
- vcazan
- Date:
- Sun Nov 22 18:03:23 2009 +0000
- Revision:
- 0:eb315142ac34
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
vcazan | 0:eb315142ac34 | 1 | #include "mbed.h" |
vcazan | 0:eb315142ac34 | 2 | |
vcazan | 0:eb315142ac34 | 3 | DigitalOut PSclock(p21); |
vcazan | 0:eb315142ac34 | 4 | DigitalIn PSdata(p22); |
vcazan | 0:eb315142ac34 | 5 | DigitalIn PSack(p23); |
vcazan | 0:eb315142ac34 | 6 | DigitalOut PScommand(p24); |
vcazan | 0:eb315142ac34 | 7 | DigitalOut PSattention(p25); |
vcazan | 0:eb315142ac34 | 8 | |
vcazan | 0:eb315142ac34 | 9 | Serial pc(USBTX, USBRX); // tx, rx |
vcazan | 0:eb315142ac34 | 10 | int temp, data0, data1, data2, data3, data4, data5, i ,debounceSelect; |
vcazan | 0:eb315142ac34 | 11 | |
vcazan | 0:eb315142ac34 | 12 | // enable interupts |
vcazan | 0:eb315142ac34 | 13 | |
vcazan | 0:eb315142ac34 | 14 | int _BV(int bit) { |
vcazan | 0:eb315142ac34 | 15 | return 1 << bit; |
vcazan | 0:eb315142ac34 | 16 | } |
vcazan | 0:eb315142ac34 | 17 | |
vcazan | 0:eb315142ac34 | 18 | // PSx controller communication function. |
vcazan | 0:eb315142ac34 | 19 | // send a byte on the command line and receive one on the data line. |
vcazan | 0:eb315142ac34 | 20 | // needs Attention pin to have gone low before called to activate controller. |
vcazan | 0:eb315142ac34 | 21 | char gameByte (char command) { |
vcazan | 0:eb315142ac34 | 22 | wait_us(1); |
vcazan | 0:eb315142ac34 | 23 | char data = 0x00; // clear data variable to save setting low bits later. |
vcazan | 0:eb315142ac34 | 24 | for (int i=0; i<8; i++) { |
vcazan | 0:eb315142ac34 | 25 | if (command & _BV(i)) { |
vcazan | 0:eb315142ac34 | 26 | PScommand=1; // bit bang "command" out on PScommand wire. |
vcazan | 0:eb315142ac34 | 27 | } else { |
vcazan | 0:eb315142ac34 | 28 | PScommand = 0; |
vcazan | 0:eb315142ac34 | 29 | } |
vcazan | 0:eb315142ac34 | 30 | PSclock = 0; // CLOCK LOW |
vcazan | 0:eb315142ac34 | 31 | wait_us(20); // wait for output to stabilise |
vcazan | 0:eb315142ac34 | 32 | //if ((PIND & _BV(PSdata)))_SFR_BYTE(data) |= _BV(i); // read PSdata pin and store |
vcazan | 0:eb315142ac34 | 33 | //else cbi(data, i); |
vcazan | 0:eb315142ac34 | 34 | PSclock = 1; // CLOCK HIGH |
vcazan | 0:eb315142ac34 | 35 | } |
vcazan | 0:eb315142ac34 | 36 | PScommand = 1; |
vcazan | 0:eb315142ac34 | 37 | |
vcazan | 0:eb315142ac34 | 38 | wait_us(20); // wait for ACK to pass. |
vcazan | 0:eb315142ac34 | 39 | |
vcazan | 0:eb315142ac34 | 40 | return data; |
vcazan | 0:eb315142ac34 | 41 | } |
vcazan | 0:eb315142ac34 | 42 | |
vcazan | 0:eb315142ac34 | 43 | |
vcazan | 0:eb315142ac34 | 44 | //sei(); |
vcazan | 0:eb315142ac34 | 45 | |
vcazan | 0:eb315142ac34 | 46 | // this loop continues to put PSx controller into analouge mode untill the |
vcazan | 0:eb315142ac34 | 47 | // controller responds with 0x73 in the 2nd byte. |
vcazan | 0:eb315142ac34 | 48 | // (PS2 controller responds with 0x73 when in analouge mode.) |
vcazan | 0:eb315142ac34 | 49 | // the status LEDs will continue to count upwards untill a controller is found. |
vcazan | 0:eb315142ac34 | 50 | // if everything is working correctly this should happen on the first pass of |
vcazan | 0:eb315142ac34 | 51 | // this loop but occasionally errors occur and a 2nd or 3rd itteration happen. |
vcazan | 0:eb315142ac34 | 52 | int chk_ana = 0, cnt = 0; |
vcazan | 0:eb315142ac34 | 53 | |
vcazan | 0:eb315142ac34 | 54 | void startup() { |
vcazan | 0:eb315142ac34 | 55 | |
vcazan | 0:eb315142ac34 | 56 | while (chk_ana != 0x73) { |
vcazan | 0:eb315142ac34 | 57 | // put controller in config mode |
vcazan | 0:eb315142ac34 | 58 | PScommand = 1; |
vcazan | 0:eb315142ac34 | 59 | PSclock = 1; |
vcazan | 0:eb315142ac34 | 60 | PSattention =0; |
vcazan | 0:eb315142ac34 | 61 | |
vcazan | 0:eb315142ac34 | 62 | gameByte(0x01); |
vcazan | 0:eb315142ac34 | 63 | gameByte(0x43); |
vcazan | 0:eb315142ac34 | 64 | gameByte(0x00); |
vcazan | 0:eb315142ac34 | 65 | gameByte(0x01); |
vcazan | 0:eb315142ac34 | 66 | gameByte(0x00); |
vcazan | 0:eb315142ac34 | 67 | |
vcazan | 0:eb315142ac34 | 68 | PScommand = 1; |
vcazan | 0:eb315142ac34 | 69 | wait_ms(1); |
vcazan | 0:eb315142ac34 | 70 | PSattention=1; |
vcazan | 0:eb315142ac34 | 71 | |
vcazan | 0:eb315142ac34 | 72 | wait_ms(10); |
vcazan | 0:eb315142ac34 | 73 | |
vcazan | 0:eb315142ac34 | 74 | // put controller in analog mode |
vcazan | 0:eb315142ac34 | 75 | PScommand = 1; |
vcazan | 0:eb315142ac34 | 76 | PSclock =1; |
vcazan | 0:eb315142ac34 | 77 | PSattention =1;; |
vcazan | 0:eb315142ac34 | 78 | |
vcazan | 0:eb315142ac34 | 79 | gameByte(0x01); |
vcazan | 0:eb315142ac34 | 80 | gameByte(0x44); |
vcazan | 0:eb315142ac34 | 81 | gameByte(0x00); |
vcazan | 0:eb315142ac34 | 82 | gameByte(0x01); |
vcazan | 0:eb315142ac34 | 83 | gameByte(0x03); |
vcazan | 0:eb315142ac34 | 84 | gameByte(0x00); |
vcazan | 0:eb315142ac34 | 85 | gameByte(0x00); |
vcazan | 0:eb315142ac34 | 86 | gameByte(0x00); |
vcazan | 0:eb315142ac34 | 87 | gameByte(0x00); |
vcazan | 0:eb315142ac34 | 88 | |
vcazan | 0:eb315142ac34 | 89 | PScommand = 1; |
vcazan | 0:eb315142ac34 | 90 | wait_ms(1); |
vcazan | 0:eb315142ac34 | 91 | PSattention =1; |
vcazan | 0:eb315142ac34 | 92 | |
vcazan | 0:eb315142ac34 | 93 | wait_ms(10); |
vcazan | 0:eb315142ac34 | 94 | |
vcazan | 0:eb315142ac34 | 95 | // exit config mode |
vcazan | 0:eb315142ac34 | 96 | PScommand = 1; |
vcazan | 0:eb315142ac34 | 97 | PSclock = 1; |
vcazan | 0:eb315142ac34 | 98 | PSattention = 1; |
vcazan | 0:eb315142ac34 | 99 | |
vcazan | 0:eb315142ac34 | 100 | gameByte(0x01); |
vcazan | 0:eb315142ac34 | 101 | gameByte(0x43); |
vcazan | 0:eb315142ac34 | 102 | gameByte(0x00); |
vcazan | 0:eb315142ac34 | 103 | gameByte(0x00); |
vcazan | 0:eb315142ac34 | 104 | gameByte(0x5A); |
vcazan | 0:eb315142ac34 | 105 | gameByte(0x5A); |
vcazan | 0:eb315142ac34 | 106 | gameByte(0x5A); |
vcazan | 0:eb315142ac34 | 107 | gameByte(0x5A); |
vcazan | 0:eb315142ac34 | 108 | gameByte(0x5A); |
vcazan | 0:eb315142ac34 | 109 | |
vcazan | 0:eb315142ac34 | 110 | PScommand = 1; |
vcazan | 0:eb315142ac34 | 111 | wait_ms(1); |
vcazan | 0:eb315142ac34 | 112 | PSattention = 1; |
vcazan | 0:eb315142ac34 | 113 | |
vcazan | 0:eb315142ac34 | 114 | wait_ms(10); |
vcazan | 0:eb315142ac34 | 115 | // poll controller and check in analouge mode. |
vcazan | 0:eb315142ac34 | 116 | PScommand = 1; |
vcazan | 0:eb315142ac34 | 117 | PSclock=1; |
vcazan | 0:eb315142ac34 | 118 | PSattention=0; |
vcazan | 0:eb315142ac34 | 119 | |
vcazan | 0:eb315142ac34 | 120 | gameByte(0x01); |
vcazan | 0:eb315142ac34 | 121 | chk_ana = gameByte(0x42); // the 2nd byte to be returned from the controller should = 0x73 for "red" analouge controller. |
vcazan | 0:eb315142ac34 | 122 | gameByte(0x00); |
vcazan | 0:eb315142ac34 | 123 | gameByte(0x00); |
vcazan | 0:eb315142ac34 | 124 | gameByte(0x00); |
vcazan | 0:eb315142ac34 | 125 | gameByte(0x00); |
vcazan | 0:eb315142ac34 | 126 | gameByte(0x00); |
vcazan | 0:eb315142ac34 | 127 | gameByte(0x00); |
vcazan | 0:eb315142ac34 | 128 | gameByte(0x00); |
vcazan | 0:eb315142ac34 | 129 | |
vcazan | 0:eb315142ac34 | 130 | PScommand = 1; |
vcazan | 0:eb315142ac34 | 131 | wait_ms(1); |
vcazan | 0:eb315142ac34 | 132 | PSattention =1; |
vcazan | 0:eb315142ac34 | 133 | |
vcazan | 0:eb315142ac34 | 134 | wait_ms(10); |
vcazan | 0:eb315142ac34 | 135 | |
vcazan | 0:eb315142ac34 | 136 | |
vcazan | 0:eb315142ac34 | 137 | // keep increasing counter to be dispalyed untill PSx controller confirms it's in analouge mode. |
vcazan | 0:eb315142ac34 | 138 | pc.putc(cnt++); |
vcazan | 0:eb315142ac34 | 139 | if (cnt > 254) { |
vcazan | 0:eb315142ac34 | 140 | cnt=0; |
vcazan | 0:eb315142ac34 | 141 | } |
vcazan | 0:eb315142ac34 | 142 | } |
vcazan | 0:eb315142ac34 | 143 | } |
vcazan | 0:eb315142ac34 | 144 | |
vcazan | 0:eb315142ac34 | 145 | |
vcazan | 0:eb315142ac34 | 146 | // main program loop: |
vcazan | 0:eb315142ac34 | 147 | void loop () { |
vcazan | 0:eb315142ac34 | 148 | |
vcazan | 0:eb315142ac34 | 149 | PScommand=1; |
vcazan | 0:eb315142ac34 | 150 | PSclock=1; |
vcazan | 0:eb315142ac34 | 151 | PSattention = 0; |
vcazan | 0:eb315142ac34 | 152 | |
vcazan | 0:eb315142ac34 | 153 | gameByte(0x01); // bite 0. header. |
vcazan | 0:eb315142ac34 | 154 | temp = gameByte(0x42); // bite 1. header. (should possibly put test on this byte to detect unplugging of controller.) |
vcazan | 0:eb315142ac34 | 155 | gameByte(0x00); // bite 2. header. |
vcazan | 0:eb315142ac34 | 156 | |
vcazan | 0:eb315142ac34 | 157 | data0 = gameByte(0x00); // bite 3. first data bite. |
vcazan | 0:eb315142ac34 | 158 | data1 = gameByte(0x00); // bite 4. |
vcazan | 0:eb315142ac34 | 159 | data2 = gameByte(0x00); // bite 5. |
vcazan | 0:eb315142ac34 | 160 | data3 = gameByte(0x00); // bite 6. |
vcazan | 0:eb315142ac34 | 161 | data4 = gameByte(0x00); // bite 7. |
vcazan | 0:eb315142ac34 | 162 | data5 = gameByte(0x00); // bite 8. |
vcazan | 0:eb315142ac34 | 163 | |
vcazan | 0:eb315142ac34 | 164 | wait_ms(1); |
vcazan | 0:eb315142ac34 | 165 | PScommand = 1; // close communication with PSx controller |
vcazan | 0:eb315142ac34 | 166 | wait_ms(1); |
vcazan | 0:eb315142ac34 | 167 | PSattention = 1; // all done. |
vcazan | 0:eb315142ac34 | 168 | |
vcazan | 0:eb315142ac34 | 169 | |
vcazan | 0:eb315142ac34 | 170 | |
vcazan | 0:eb315142ac34 | 171 | if (!(data0 & _BV(0)) && !debounceSelect) { // capture one unique press of the "select" button |
vcazan | 0:eb315142ac34 | 172 | debounceSelect = 1; |
vcazan | 0:eb315142ac34 | 173 | } else if ((data0 & _BV(0)) && debounceSelect) { |
vcazan | 0:eb315142ac34 | 174 | if (i++ >= 5) i=0; |
vcazan | 0:eb315142ac34 | 175 | debounceSelect = 0; |
vcazan | 0:eb315142ac34 | 176 | } |
vcazan | 0:eb315142ac34 | 177 | |
vcazan | 0:eb315142ac34 | 178 | |
vcazan | 0:eb315142ac34 | 179 | // this switch decides which data register to show on status LEDs depending on how many times |
vcazan | 0:eb315142ac34 | 180 | // the "select" button on the PS2 controller has been pressed. |
vcazan | 0:eb315142ac34 | 181 | switch (i) { |
vcazan | 0:eb315142ac34 | 182 | case 0: |
vcazan | 0:eb315142ac34 | 183 | pc.printf("case 0: %d\n", data0); |
vcazan | 0:eb315142ac34 | 184 | break; |
vcazan | 0:eb315142ac34 | 185 | case 1: |
vcazan | 0:eb315142ac34 | 186 | pc.printf("case 1: %d\n", data1); |
vcazan | 0:eb315142ac34 | 187 | break; |
vcazan | 0:eb315142ac34 | 188 | case 2: |
vcazan | 0:eb315142ac34 | 189 | pc.printf("case 2: %d\n", data2); |
vcazan | 0:eb315142ac34 | 190 | break; |
vcazan | 0:eb315142ac34 | 191 | case 3: |
vcazan | 0:eb315142ac34 | 192 | pc.printf("case 3: %d\n", data3); |
vcazan | 0:eb315142ac34 | 193 | break; |
vcazan | 0:eb315142ac34 | 194 | case 4: |
vcazan | 0:eb315142ac34 | 195 | pc.printf("case 4: %d\n", data4); |
vcazan | 0:eb315142ac34 | 196 | break; |
vcazan | 0:eb315142ac34 | 197 | case 5: |
vcazan | 0:eb315142ac34 | 198 | pc.printf("case 5: %d\n", data5); |
vcazan | 0:eb315142ac34 | 199 | } |
vcazan | 0:eb315142ac34 | 200 | |
vcazan | 0:eb315142ac34 | 201 | pc.printf("$d\n",data1); |
vcazan | 0:eb315142ac34 | 202 | } //void loop |
vcazan | 0:eb315142ac34 | 203 | |
vcazan | 0:eb315142ac34 | 204 | |
vcazan | 0:eb315142ac34 | 205 | int main() { |
vcazan | 0:eb315142ac34 | 206 | startup(); |
vcazan | 0:eb315142ac34 | 207 | while (1) { |
vcazan | 0:eb315142ac34 | 208 | loop(); |
vcazan | 0:eb315142ac34 | 209 | } |
vcazan | 0:eb315142ac34 | 210 | } |