├── README.md ├── Trackpoint.cpp ├── Trackpoint.h └── examples └── basics └── basics.pde /README.md: -------------------------------------------------------------------------------- 1 | Introduction 2 | ============ 3 | 4 | Arduino library for interfacing with an IBM TrackPoint 5 | 6 | Tested with Arduino IDE: 1.0.5 7 | 8 | See also the [TrackPoint System Version 4.0 Engineering Specification][1]. 9 | 10 | **Update:** This library only supports interfacing with the TrackPoint in 11 | *remote mode*; For a library that supports *stream mode*, have a look at Cong 12 | Nguyen’s [arduino-trackpoint-extended][2]. 13 | 14 | 15 | License 16 | ======= 17 | 18 | Copyright (C) 2013 [Felix E. Klee](mailto:felix.klee@inka.de) 19 | 20 | Based on Chris J. Kiick's Arduino PS/2 library, released in January 2008 into 21 | the public domain. 22 | 23 | Permission is hereby granted, free of charge, to any person obtaining a copy of 24 | this software and associated documentation files (the "Software"), to deal in 25 | the Software without restriction, including without limitation the rights to 26 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 27 | of the Software, and to permit persons to whom the Software is furnished to do 28 | so, subject to the following conditions: 29 | 30 | The above copyright notice and this permission notice shall be included in all 31 | copies or substantial portions of the Software. 32 | 33 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 34 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 35 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 36 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 37 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 38 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 39 | SOFTWARE. 40 | 41 | 42 | [1]: http://blogs.epfl.ch/icenet/documents/Ykt3Eext.pdf 43 | [2]: https://github.com/rampadc/arduino-trackpoint-extended 44 | -------------------------------------------------------------------------------- /Trackpoint.cpp: -------------------------------------------------------------------------------- 1 | // For interfacing with a TrackPoint 4, or a compatible device. 2 | // 3 | // Based on the Arduino PS/2 library (`ps2.h`, `ps2.cpp`), written by Chris J. 4 | // Kiick in January 2008 and released into the public domain. As of August 5 | // 2013, it is available on: 6 | // 7 | // 8 | // 9 | // Limitations according to `ps2.cpp`: 10 | // 11 | // * We do not handle parity errors. 12 | // 13 | // * The timing constants are hard coded from the spec. Data rate is not 14 | // impressive. 15 | // 16 | // * Probably lots of room for optimization. 17 | 18 | // Copyright (C) 2013 [Felix E. Klee](mailto:felix.klee@inka.de) 19 | // 20 | // Based on Chris J. Kiick's Arduino PS/2 library, released in January 2008 21 | // into the public domain. 22 | // 23 | // Permission is hereby granted, free of charge, to any person obtaining a copy 24 | // of this software and associated documentation files (the "Software"), to 25 | // deal in the Software without restriction, including without limitation the 26 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 27 | // sell copies of the Software, and to permit persons to whom the Software is 28 | // furnished to do so, subject to the following conditions: 29 | // 30 | // The above copyright notice and this permission notice shall be included in 31 | // all copies or substantial portions of the Software. 32 | // 33 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 34 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 35 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 36 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 37 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 38 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 39 | // IN THE SOFTWARE. 40 | 41 | #include "Trackpoint.h" 42 | 43 | Trackpoint::Trackpoint(byte clkPin, byte dataPin, byte resetPin) : 44 | _resetPin(resetPin), _clkPin(clkPin), _dataPin(dataPin) 45 | { 46 | gohi(_clkPin); 47 | gohi(_dataPin); 48 | } 49 | 50 | // errors are ignored 51 | void Trackpoint::writeToRamLocation(byte location, byte value) { 52 | write(0xe2); 53 | read(); // ACK 54 | write(0x81); 55 | read(); // ACK 56 | write(location); 57 | read(); // ACK 58 | write(value); 59 | read(); // ACK 60 | } 61 | 62 | // undefined in case of error 63 | byte Trackpoint::readFromRamLocation(byte location) { 64 | write(0xe2); 65 | read(); // ACK 66 | write(0x80); 67 | read(); // ACK 68 | write(location); 69 | read(); // ACK 70 | return read(); 71 | } 72 | 73 | void Trackpoint::setSensitivityFactor(byte sensitivityFactor) { 74 | writeToRamLocation(0x4a, sensitivityFactor); 75 | } 76 | 77 | byte Trackpoint::sensitivityFactor() { 78 | return readFromRamLocation(0x4a); 79 | } 80 | 81 | void Trackpoint::setRemoteMode() { 82 | write(0xf0); 83 | read(); 84 | } 85 | 86 | void Trackpoint::reset() { 87 | pinMode(_resetPin, OUTPUT); 88 | digitalWrite(_resetPin, HIGH); 89 | delay(2000); // empirical value 90 | digitalWrite(_resetPin, LOW); 91 | } 92 | 93 | Trackpoint::DataReport Trackpoint::readData() { 94 | DataReport d; 95 | 96 | write(0xeb); 97 | read(); // ACK 98 | d.state = read(); 99 | d.x = read(); 100 | d.y = read(); 101 | 102 | return d; 103 | } 104 | 105 | // Comments and code below mostly unchanged from `ps2.h`. 106 | 107 | /* 108 | * according to some code I saw, these functions will 109 | * correctly set the clock and data pins for 110 | * various conditions. It's done this way so you don't need 111 | * pullup resistors. 112 | */ 113 | void Trackpoint::gohi(byte pin) { 114 | pinMode(pin, INPUT); 115 | digitalWrite(pin, HIGH); 116 | } 117 | 118 | void Trackpoint::golo(byte pin) { 119 | pinMode(pin, OUTPUT); 120 | digitalWrite(pin, LOW); 121 | } 122 | 123 | /* write a byte to the PS2 device */ 124 | void Trackpoint::write(byte data) { 125 | byte i; 126 | byte parity = 1; 127 | 128 | gohi(_dataPin); 129 | gohi(_clkPin); 130 | delayMicroseconds(300); 131 | golo(_clkPin); 132 | delayMicroseconds(300); 133 | golo(_dataPin); 134 | delayMicroseconds(10); 135 | gohi(_clkPin); // start bit 136 | /* wait for device to take control of clock */ 137 | while (digitalRead(_clkPin) == HIGH) 138 | ; // this loop intentionally left blank 139 | // clear to send data 140 | for (i=0; i < 8; i++) 141 | { 142 | if (data & 0x01) 143 | { 144 | gohi(_dataPin); 145 | } else { 146 | golo(_dataPin); 147 | } 148 | // wait for clock 149 | while (digitalRead(_clkPin) == LOW) 150 | ; 151 | while (digitalRead(_clkPin) == HIGH) 152 | ; 153 | parity = parity ^ (data & 0x01); 154 | data = data >> 1; 155 | } 156 | // parity bit 157 | if (parity) 158 | { 159 | gohi(_dataPin); 160 | } else { 161 | golo(_dataPin); 162 | } 163 | // clock cycle - like ack. 164 | while (digitalRead(_clkPin) == LOW) 165 | ; 166 | while (digitalRead(_clkPin) == HIGH) 167 | ; 168 | // stop bit 169 | gohi(_dataPin); 170 | delayMicroseconds(50); 171 | while (digitalRead(_clkPin) == HIGH) 172 | ; 173 | // mode switch 174 | while ((digitalRead(_clkPin) == LOW) || (digitalRead(_dataPin) == LOW)) 175 | ; 176 | // hold up incoming data 177 | golo(_clkPin); 178 | } 179 | 180 | 181 | /* 182 | * read a byte of data from the ps2 device. Ignores parity. 183 | */ 184 | byte Trackpoint::read(void) { 185 | byte data = 0x00; 186 | byte i; 187 | byte bit = 0x01; 188 | 189 | // start clock 190 | gohi(_clkPin); 191 | gohi(_dataPin); 192 | delayMicroseconds(50); 193 | while (digitalRead(_clkPin) == HIGH) 194 | ; 195 | delayMicroseconds(5); // not sure why. 196 | while (digitalRead(_clkPin) == LOW) 197 | ; // eat start bit 198 | for (i=0; i < 8; i++) 199 | { 200 | while (digitalRead(_clkPin) == HIGH) 201 | ; 202 | if (digitalRead(_dataPin) == HIGH) 203 | { 204 | data = data | bit; 205 | } 206 | while (digitalRead(_clkPin) == LOW) 207 | ; 208 | bit = bit << 1; 209 | } 210 | // eat parity bit, ignore it. 211 | while (digitalRead(_clkPin) == HIGH) 212 | ; 213 | while (digitalRead(_clkPin) == LOW) 214 | ; 215 | // eat stop bit 216 | while (digitalRead(_clkPin) == HIGH) 217 | ; 218 | while (digitalRead(_clkPin) == LOW) 219 | ; 220 | golo(_clkPin); // hold incoming data 221 | 222 | return data; 223 | } 224 | -------------------------------------------------------------------------------- /Trackpoint.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013 [Felix E. Klee](mailto:felix.klee@inka.de) 2 | // 3 | // Based on Chris J. Kiick's Arduino PS/2 library, released in January 2008 4 | // into the public domain. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to 8 | // deal in the Software without restriction, including without limitation the 9 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | // sell copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 | // IN THE SOFTWARE. 23 | 24 | #ifndef Trackpoint_h 25 | #define Trackpoint_h 26 | 27 | #include "Arduino.h" 28 | 29 | class Trackpoint { 30 | public: 31 | struct DataReport { 32 | byte state; 33 | byte x; 34 | byte y; 35 | }; 36 | 37 | Trackpoint(byte clkPin, byte dataPin, byte resetPin); 38 | void writeToRamLocation(byte location, byte value); 39 | byte readFromRamLocation(byte location); 40 | void setSensitivityFactor(byte sensitivity); 41 | byte sensitivityFactor(); 42 | void setRemoteMode(); 43 | void reset(); 44 | DataReport readData(); 45 | void write(byte data); 46 | byte read(void); 47 | 48 | private: 49 | byte _resetPin; 50 | byte _clkPin; 51 | byte _dataPin; 52 | 53 | void golo(byte pin); 54 | void gohi(byte pin); 55 | }; 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /examples/basics/basics.pde: -------------------------------------------------------------------------------- 1 | // Allows control of the mouse cursor on the connected computer, via a 2 | // TrackPoint. 3 | // 4 | // Tested with an Arduino Micro (Leonardo compatible). 5 | 6 | // Copyright (C) 2013 Felix E. Klee 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to 10 | // deal in the Software without restriction, including without limitation the 11 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 12 | // sell copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 24 | // IN THE SOFTWARE. 25 | 26 | #include "Trackpoint.h" 27 | 28 | Trackpoint trackpoint(8, // CLK 29 | 9, // DATA 30 | 12); // RESET 31 | 32 | void setup() { 33 | Mouse.begin(); 34 | trackpoint.reset(); 35 | trackpoint.setRemoteMode(); 36 | trackpoint.setSensitivityFactor(0xc0); // more sensitive than by default 37 | } 38 | 39 | void sendButtonState(byte state) { 40 | static const char hidStates[] = {MOUSE_LEFT, MOUSE_RIGHT}; 41 | 42 | for (byte i = 0; i < sizeof(hidStates); i++) { 43 | byte hidState = hidStates[i]; 44 | if (state & (1 << i)) { 45 | Mouse.press(hidState); 46 | } else if (Mouse.isPressed(hidState)) { 47 | Mouse.release(hidState); 48 | } 49 | } 50 | } 51 | 52 | // Reads TrackPoint data and sends data to computer. 53 | void loop() { 54 | Trackpoint::DataReport d = trackpoint.readData(); 55 | 56 | if (d.state & (1 << 2)) { // middle button down => scroll 57 | Mouse.move(0, 0, d.y); 58 | } else { 59 | Mouse.move(d.x, -d.y, 0); 60 | sendButtonState(d.state); 61 | } 62 | } 63 | --------------------------------------------------------------------------------