Using Those Old PS2 Mouses You Couldn’t Throw Out
Sorry got totally distracted by a box in the basement with some PS2 Intellimouse parts in it this weekend. I’ll have those Box2D shortcuts updated soon, promise.
Anyway if you’d like to get a PS2 Microsoft Intellimouse with wheel fully working with a current (Diecimila or newer) Arduino here’s the corrected code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 | /** * Code is a mix of ps2mouse from the Arduino playground * and mousewheel code from "a world in dk" modified to * work with Arduino Decimilia and 0017, and run a PS2 * Microsoft Intellimouse. * * Collin Reidorf collin@paperclipped.com * Repaired http://blowingthroughlines.com */ /* * an arduino sketch to interface with a ps/2 mouse. * Also uses serial protocol to talk back to the host * and report what it finds. */ /* * Pin 5 is the mouse data pin, pin 6 is the clock pin * Feel free to use whatever pins are convenient. */ #define MDATA 5 #define MCLK 6 /* * according to some code I saw, these functions will * correctly set the mouse clock and data pins for * various conditions. */ void gohi(int pin) { pinMode(pin, INPUT); digitalWrite(pin, HIGH); } void golo(int pin) { pinMode(pin, OUTPUT); digitalWrite(pin, LOW); } /* PRECONDITION : clock is HIGH */ /* sends a single bit and returns with clock high */ void sendBit(char bit) { if (bit) { gohi(MDATA); } else { golo(MDATA); } /* wait for clock cycle */ while (digitalRead(MCLK) == LOW) ; while (digitalRead(MCLK) == HIGH) ; } /* reads a single bit and returns with clock low */ char readBit() { char tmp = 0x00; while (digitalRead(MCLK) == HIGH) ; if (digitalRead(MDATA) == HIGH) tmp = 0x01; while (digitalRead(MCLK) == LOW) ; return tmp; } void mouse_write(char data) { char i; char parity = 1; /* put pins in output mode */ gohi(MDATA); gohi(MCLK); delayMicroseconds(300); golo(MCLK); delayMicroseconds(300); golo(MDATA); delayMicroseconds(10); /* start bit */ gohi(MCLK); /* wait for mouse to take control of clock); */ sendBit(0); /* clock is low, and we are clear to send data */ for (i=0; i < 8; i++) { sendBit(data & 0x01); parity = parity ^ (data & 0x01); // might not need this anymore but too lazy to test... data = data >> 1; } /* parity */ sendBit(parity); /* stop bit */ sendBit(1); /* wait for mouse to switch modes */ while ((digitalRead(MCLK) == LOW) || (digitalRead(MDATA) == LOW)) ; /* put a hold on the incoming data. */ golo(MCLK); } /* * Get a byte of data from the mouse */ char mouse_read(void) { char data = 0x00; int i; char bit = 0x01; // Serial.print("reading byte from mouse\n"); /* start the clock */ gohi(MCLK); gohi(MDATA); delayMicroseconds(50); readBit(); // delayMicroseconds(5); /* not sure why */ // and not evidently needed for (i=0; i < 8; i++) { // read the bits data = data | (readBit()<<i); } /* eat parity bit, which we ignore */ readBit(); /* eat stop bit */ readBit(); /* put a hold on the incoming data. */ golo(MCLK); return data; } // for the mousewheel // #define verbose // for verbose output unsigned char msInitSequence[7]; // should go up on top when ready char writeAndGetResponse(char data) { // #ifdef verbose // Serial.print("sending : "); // Serial.print((unsigned char)data, HEX); // Serial.print("\t"); // #endif mouse_write( data ); return response(); } char response() { char data = mouse_read(); // #ifdef verbose // Serial.print("echo "); // Serial.print((unsigned char)data, HEX); // Serial.print(" from mouse\n"); // #endif return data; } // void msMode() { // sequence for ms mode (3 button + scroll) // this is a entering procedure and i guess it will // work with other mice/ICs as its problably stadard ps2 // And using an array were just a quick way to handle them msInitSequence[0] =0xF3; msInitSequence[1] =0xC8; msInitSequence[2] =0xF3; msInitSequence[3] =0x64; msInitSequence[4] =0xF3; msInitSequence[5] =0x50; msInitSequence[6] =0xF2; int i; for(i=0;i<7;i++) writeAndGetResponse(msInitSequence[i]); } // end of mousewheel stuff void showMStat(char mstat) { int i; char bit = 0x01; for(i = 0; i<8; i++) { if(mstat&bit) { Serial.print("\t"); switch(i) { case 0: Serial.print("L"); break; case 1: Serial.print("R"); break; case 2: Serial.print("M"); break; case 3: // Serial.print(" Reserve ...\t"); break; case 4: // Serial.print(" X data negative \t"); break; case 5: // Serial.print("Y data negative \t"); break; case 6: Serial.print("X data overflow"); break; case 7: Serial.print("Y data overflow"); break; } } bit = bit<<1; } } void mouse_init() { gohi(MCLK); gohi(MDATA); // Serial.print("Sending reset to mouse\n"); mouse_write(0xff); mouse_read(); /* ack byte */ // Serial.print("Read ack byte1\n"); mouse_read(); /* blank */ mouse_read(); /* blank */ msMode(); // mousewheel code // Serial.print("Sending remote mode code\n"); mouse_write(0xf0); /* remote mode */ mouse_read(); /* ack */ // Serial.print("Read ack byte2\n"); delayMicroseconds(100); } void setup() { Serial.begin(9600); mouse_init(); } /* * get a reading from the mouse and report it back to the * host via the serial line. */ void loop() { char mstat; char mx; char my; char mz; /* get a reading from the mouse */ writeAndGetResponse(0xEB); /* give me data! */ mstat = mouse_read(); mx = mouse_read(); my = mouse_read(); mz = mouse_read(); /* send the data back up */ Serial.print("\tmouse status="); Serial.print(mstat, BIN); Serial.print("\tX="); Serial.print(mx, DEC); Serial.print("\tY="); Serial.print(my, DEC); Serial.print("\tZ="); Serial.print(mz, DEC); showMStat(mstat); // print buttons that are down Serial.println(); delay(20); /* twiddle */ } |
Based on code from The Arduino Playground which also shows the pinouts (where the black and white drawing is the female connector’s pintout, the pins on the mouse itself are a mirror image, like in the blurry photo below) and more code from A world in dk(decay/denmark).
