Aleksandar Kodzhabashev
/
TrackballQuery
An example of using polling PS/2 using the modified mbed PS/2 library
mylib/PS2/PS2MS.cpp@10:37e7c46837dc, 2014-03-10 (annotated)
- Committer:
- d3alek
- Date:
- Mon Mar 10 20:43:52 2014 +0000
- Revision:
- 10:37e7c46837dc
- Parent:
- 9:2c85d7f99a14
- Child:
- 11:f5dcf8811a4e
Servo movement completed notification working
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
d3alek | 0:94cffad90b69 | 1 | /** |
d3alek | 0:94cffad90b69 | 2 | * PS/2 mouse interface control class (Version 0.0.1) |
d3alek | 0:94cffad90b69 | 3 | * |
d3alek | 0:94cffad90b69 | 4 | * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) |
d3alek | 0:94cffad90b69 | 5 | * http://shinta.main.jp/ |
d3alek | 0:94cffad90b69 | 6 | */ |
d3alek | 0:94cffad90b69 | 7 | |
d3alek | 0:94cffad90b69 | 8 | #include "PS2MS.h" |
d3alek | 0:94cffad90b69 | 9 | |
d3alek | 10:37e7c46837dc | 10 | #define DEBUG false |
d3alek | 10:37e7c46837dc | 11 | |
d3alek | 0:94cffad90b69 | 12 | /** |
d3alek | 0:94cffad90b69 | 13 | * Create. |
d3alek | 0:94cffad90b69 | 14 | * |
d3alek | 0:94cffad90b69 | 15 | * @param clk_pin Clock pin. |
d3alek | 0:94cffad90b69 | 16 | * @param dat_pin Data pin. |
d3alek | 0:94cffad90b69 | 17 | */ |
d3alek | 0:94cffad90b69 | 18 | PS2MS::PS2MS(PinName clk_pin, PinName dat_pin) |
d3alek | 10:37e7c46837dc | 19 | : clk(clk_pin), dat(dat_pin), clkOut(clk_pin), mSending(false), mInFuncFall(false) |
d3alek | 10:37e7c46837dc | 20 | { |
d3alek | 0:94cffad90b69 | 21 | init_work(); |
d3alek | 10:37e7c46837dc | 22 | dat.input(); |
d3alek | 0:94cffad90b69 | 23 | clk.fall(this, &PS2MS::func_fall); |
d3alek | 0:94cffad90b69 | 24 | timeout = 1; |
d3alek | 0:94cffad90b69 | 25 | } |
d3alek | 0:94cffad90b69 | 26 | |
d3alek | 0:94cffad90b69 | 27 | /** |
d3alek | 0:94cffad90b69 | 28 | * Destory. |
d3alek | 0:94cffad90b69 | 29 | */ |
d3alek | 10:37e7c46837dc | 30 | PS2MS::~PS2MS() |
d3alek | 10:37e7c46837dc | 31 | { |
d3alek | 0:94cffad90b69 | 32 | wdt.detach(); |
d3alek | 0:94cffad90b69 | 33 | } |
d3alek | 0:94cffad90b69 | 34 | |
d3alek | 10:37e7c46837dc | 35 | int PS2MS::getc() |
d3alek | 10:37e7c46837dc | 36 | { |
d3alek | 0:94cffad90b69 | 37 | tot.reset(); |
d3alek | 0:94cffad90b69 | 38 | tot.start(); |
d3alek | 0:94cffad90b69 | 39 | while (work.cStart == work.cEnd) { |
d3alek | 0:94cffad90b69 | 40 | wait_ms(1); |
d3alek | 0:94cffad90b69 | 41 | if ((timeout > 0) && (tot.read_ms() > timeout)) { |
d3alek | 10:37e7c46837dc | 42 | printf("T "); |
d3alek | 0:94cffad90b69 | 43 | return EOF; |
d3alek | 0:94cffad90b69 | 44 | } |
d3alek | 0:94cffad90b69 | 45 | } |
d3alek | 0:94cffad90b69 | 46 | tot.stop(); |
d3alek | 0:94cffad90b69 | 47 | |
d3alek | 0:94cffad90b69 | 48 | char c = work.buffer[work.cStart++]; |
d3alek | 0:94cffad90b69 | 49 | work.cStart = work.cStart % RINGBUFSIZ; |
d3alek | 10:37e7c46837dc | 50 | |
d3alek | 0:94cffad90b69 | 51 | return c; |
d3alek | 0:94cffad90b69 | 52 | } |
d3alek | 0:94cffad90b69 | 53 | |
d3alek | 10:37e7c46837dc | 54 | |
d3alek | 10:37e7c46837dc | 55 | |
d3alek | 10:37e7c46837dc | 56 | int PS2MS::sendCommand(char c) |
d3alek | 10:37e7c46837dc | 57 | { |
d3alek | 10:37e7c46837dc | 58 | while (mInFuncFall) { |
d3alek | 10:37e7c46837dc | 59 | continue; |
d3alek | 10:37e7c46837dc | 60 | } |
d3alek | 10:37e7c46837dc | 61 | mSending = true; |
d3alek | 10:37e7c46837dc | 62 | if (DEBUG) printf("S "); |
d3alek | 10:37e7c46837dc | 63 | dat.output(); |
d3alek | 10:37e7c46837dc | 64 | clkOut.output(); |
d3alek | 10:37e7c46837dc | 65 | clkOut.write(0); |
d3alek | 10:37e7c46837dc | 66 | wait_us(200); |
d3alek | 10:37e7c46837dc | 67 | |
d3alek | 10:37e7c46837dc | 68 | dat.write(0); |
d3alek | 10:37e7c46837dc | 69 | wait_us(10); |
d3alek | 10:37e7c46837dc | 70 | clkOut.write(1); |
d3alek | 10:37e7c46837dc | 71 | clkOut.input(); |
d3alek | 10:37e7c46837dc | 72 | |
d3alek | 10:37e7c46837dc | 73 | int parcnt = 0; |
d3alek | 10:37e7c46837dc | 74 | for (int i = 0; i < 10; i++) { |
d3alek | 10:37e7c46837dc | 75 | if (!waitClockDownEdge()) { |
d3alek | 10:37e7c46837dc | 76 | mSending = false; |
d3alek | 10:37e7c46837dc | 77 | wait_us(50); |
d3alek | 10:37e7c46837dc | 78 | if (DEBUG) printf("R "); |
d3alek | 10:37e7c46837dc | 79 | return -1; |
d3alek | 10:37e7c46837dc | 80 | } |
d3alek | 10:37e7c46837dc | 81 | if ((0 <= i) && (i <= 7)) { |
d3alek | 10:37e7c46837dc | 82 | /* |
d3alek | 10:37e7c46837dc | 83 | * Data bit. |
d3alek | 10:37e7c46837dc | 84 | */ |
d3alek | 10:37e7c46837dc | 85 | if ((c & (1 << i)) == 0) { |
d3alek | 10:37e7c46837dc | 86 | dat.write(0); |
d3alek | 10:37e7c46837dc | 87 | } else { |
d3alek | 10:37e7c46837dc | 88 | dat.write(1); |
d3alek | 10:37e7c46837dc | 89 | parcnt++; |
d3alek | 10:37e7c46837dc | 90 | } |
d3alek | 10:37e7c46837dc | 91 | } |
d3alek | 10:37e7c46837dc | 92 | if (i == 8) { |
d3alek | 10:37e7c46837dc | 93 | /* |
d3alek | 10:37e7c46837dc | 94 | * Parity bit. |
d3alek | 10:37e7c46837dc | 95 | */ |
d3alek | 10:37e7c46837dc | 96 | if ((parcnt % 2) == 0) { |
d3alek | 10:37e7c46837dc | 97 | dat.write(1); |
d3alek | 10:37e7c46837dc | 98 | } else { |
d3alek | 10:37e7c46837dc | 99 | dat.write(0); |
d3alek | 10:37e7c46837dc | 100 | } |
d3alek | 10:37e7c46837dc | 101 | } |
d3alek | 10:37e7c46837dc | 102 | if (i == 9) { |
d3alek | 10:37e7c46837dc | 103 | /* |
d3alek | 10:37e7c46837dc | 104 | * Stop bit. |
d3alek | 10:37e7c46837dc | 105 | */ |
d3alek | 10:37e7c46837dc | 106 | dat.write(1); |
d3alek | 10:37e7c46837dc | 107 | } |
d3alek | 10:37e7c46837dc | 108 | } |
d3alek | 10:37e7c46837dc | 109 | |
d3alek | 10:37e7c46837dc | 110 | dat.input(); |
d3alek | 10:37e7c46837dc | 111 | /* |
d3alek | 10:37e7c46837dc | 112 | * Check a ACK. |
d3alek | 10:37e7c46837dc | 113 | */ |
d3alek | 10:37e7c46837dc | 114 | if (!waitClockDownEdge()) { |
d3alek | 10:37e7c46837dc | 115 | mSending = false; |
d3alek | 10:37e7c46837dc | 116 | wait_us(50); |
d3alek | 10:37e7c46837dc | 117 | if (DEBUG) printf("R "); |
d3alek | 10:37e7c46837dc | 118 | return -2; |
d3alek | 10:37e7c46837dc | 119 | } |
d3alek | 10:37e7c46837dc | 120 | if (dat.read() != 0) { |
d3alek | 10:37e7c46837dc | 121 | mSending = false; |
d3alek | 10:37e7c46837dc | 122 | wait_us(50); |
d3alek | 10:37e7c46837dc | 123 | if (DEBUG) printf("R "); |
d3alek | 10:37e7c46837dc | 124 | return -3; |
d3alek | 10:37e7c46837dc | 125 | } |
d3alek | 10:37e7c46837dc | 126 | |
d3alek | 10:37e7c46837dc | 127 | if (!waitClockUpLevel()) { |
d3alek | 10:37e7c46837dc | 128 | mSending = false; |
d3alek | 10:37e7c46837dc | 129 | wait_us(50); |
d3alek | 10:37e7c46837dc | 130 | if (DEBUG) printf("R "); |
d3alek | 10:37e7c46837dc | 131 | return -4; |
d3alek | 10:37e7c46837dc | 132 | } |
d3alek | 10:37e7c46837dc | 133 | mSending = false; |
d3alek | 10:37e7c46837dc | 134 | if (DEBUG) printf("E "); |
d3alek | 10:37e7c46837dc | 135 | wait_us(50); |
d3alek | 10:37e7c46837dc | 136 | |
d3alek | 10:37e7c46837dc | 137 | return 0; |
d3alek | 10:37e7c46837dc | 138 | } |
d3alek | 10:37e7c46837dc | 139 | |
d3alek | 10:37e7c46837dc | 140 | /** |
d3alek | 10:37e7c46837dc | 141 | * Wait a clock up level. |
d3alek | 10:37e7c46837dc | 142 | * |
d3alek | 10:37e7c46837dc | 143 | * @return true if wait done. |
d3alek | 10:37e7c46837dc | 144 | */ |
d3alek | 10:37e7c46837dc | 145 | bool PS2MS::waitClockUpLevel(void) |
d3alek | 10:37e7c46837dc | 146 | { |
d3alek | 10:37e7c46837dc | 147 | int cnt; |
d3alek | 10:37e7c46837dc | 148 | /* |
d3alek | 10:37e7c46837dc | 149 | * Wait until clock is low. |
d3alek | 10:37e7c46837dc | 150 | */ |
d3alek | 10:37e7c46837dc | 151 | cnt = 0; |
d3alek | 10:37e7c46837dc | 152 | clkOut.input(); |
d3alek | 10:37e7c46837dc | 153 | while (clkOut.read() == 0) { |
d3alek | 10:37e7c46837dc | 154 | cnt++; |
d3alek | 10:37e7c46837dc | 155 | if (MAX_RETRY < cnt) { |
d3alek | 10:37e7c46837dc | 156 | return false; |
d3alek | 10:37e7c46837dc | 157 | } |
d3alek | 10:37e7c46837dc | 158 | wait_us(1); |
d3alek | 10:37e7c46837dc | 159 | } |
d3alek | 10:37e7c46837dc | 160 | return true; |
d3alek | 10:37e7c46837dc | 161 | } |
d3alek | 10:37e7c46837dc | 162 | |
d3alek | 10:37e7c46837dc | 163 | /** |
d3alek | 10:37e7c46837dc | 164 | * Wait a clock down edge. |
d3alek | 10:37e7c46837dc | 165 | * |
d3alek | 10:37e7c46837dc | 166 | * @return true if wait done. |
d3alek | 10:37e7c46837dc | 167 | */ |
d3alek | 10:37e7c46837dc | 168 | |
d3alek | 10:37e7c46837dc | 169 | bool PS2MS::waitClockDownEdge(void) |
d3alek | 10:37e7c46837dc | 170 | { |
d3alek | 10:37e7c46837dc | 171 | //tot.reset(); |
d3alek | 10:37e7c46837dc | 172 | //tot.start(); |
d3alek | 10:37e7c46837dc | 173 | //while (work.cStart == work.cEnd) { |
d3alek | 10:37e7c46837dc | 174 | // if (tot.read_ms() > CLOCK_DOWN_EDGE_WAIT_MS) { |
d3alek | 10:37e7c46837dc | 175 | // tot.stop(); |
d3alek | 10:37e7c46837dc | 176 | // return false; |
d3alek | 10:37e7c46837dc | 177 | // } |
d3alek | 10:37e7c46837dc | 178 | //} |
d3alek | 10:37e7c46837dc | 179 | //tot.stop(); |
d3alek | 10:37e7c46837dc | 180 | |
d3alek | 10:37e7c46837dc | 181 | // char c = work.buffer[work.cStart++]; |
d3alek | 10:37e7c46837dc | 182 | //work.cStart = work.cStart % RINGBUFSIZ; |
d3alek | 10:37e7c46837dc | 183 | |
d3alek | 10:37e7c46837dc | 184 | //return c; |
d3alek | 10:37e7c46837dc | 185 | int cnt; |
d3alek | 10:37e7c46837dc | 186 | /* |
d3alek | 10:37e7c46837dc | 187 | * Wait until clock is low. |
d3alek | 10:37e7c46837dc | 188 | */ |
d3alek | 10:37e7c46837dc | 189 | cnt = 0; |
d3alek | 10:37e7c46837dc | 190 | clkOut.input(); |
d3alek | 10:37e7c46837dc | 191 | while (clkOut.read() == 0) { |
d3alek | 10:37e7c46837dc | 192 | cnt++; |
d3alek | 10:37e7c46837dc | 193 | if (MAX_RETRY < cnt) { |
d3alek | 10:37e7c46837dc | 194 | return false; |
d3alek | 10:37e7c46837dc | 195 | } |
d3alek | 10:37e7c46837dc | 196 | wait_us(1); |
d3alek | 10:37e7c46837dc | 197 | } |
d3alek | 10:37e7c46837dc | 198 | /* |
d3alek | 10:37e7c46837dc | 199 | * Wait until clock is high. |
d3alek | 10:37e7c46837dc | 200 | */ |
d3alek | 10:37e7c46837dc | 201 | cnt = 0; |
d3alek | 10:37e7c46837dc | 202 | while (clkOut.read() == 1) { |
d3alek | 10:37e7c46837dc | 203 | cnt++; |
d3alek | 10:37e7c46837dc | 204 | if (MAX_RETRY < cnt) { |
d3alek | 10:37e7c46837dc | 205 | return false; |
d3alek | 10:37e7c46837dc | 206 | } |
d3alek | 10:37e7c46837dc | 207 | wait_us(1); |
d3alek | 10:37e7c46837dc | 208 | } |
d3alek | 10:37e7c46837dc | 209 | return true; |
d3alek | 10:37e7c46837dc | 210 | } |
d3alek | 10:37e7c46837dc | 211 | |
d3alek | 0:94cffad90b69 | 212 | /** |
d3alek | 0:94cffad90b69 | 213 | * Set timeout. |
d3alek | 0:94cffad90b69 | 214 | * |
d3alek | 0:94cffad90b69 | 215 | * @param ms Timeout ms. |
d3alek | 0:94cffad90b69 | 216 | */ |
d3alek | 10:37e7c46837dc | 217 | void PS2MS::setTimeout(int ms) |
d3alek | 10:37e7c46837dc | 218 | { |
d3alek | 0:94cffad90b69 | 219 | timeout = ms; |
d3alek | 0:94cffad90b69 | 220 | } |
d3alek | 0:94cffad90b69 | 221 | |
d3alek | 10:37e7c46837dc | 222 | void PS2MS::func_timeout(void) |
d3alek | 10:37e7c46837dc | 223 | { |
d3alek | 0:94cffad90b69 | 224 | work.bitcnt = 0; |
d3alek | 0:94cffad90b69 | 225 | } |
d3alek | 0:94cffad90b69 | 226 | |
d3alek | 10:37e7c46837dc | 227 | void PS2MS::func_fall(void) |
d3alek | 10:37e7c46837dc | 228 | { |
d3alek | 10:37e7c46837dc | 229 | if (mSending) { |
d3alek | 10:37e7c46837dc | 230 | return; |
d3alek | 10:37e7c46837dc | 231 | } |
d3alek | 10:37e7c46837dc | 232 | mInFuncFall = true; |
d3alek | 0:94cffad90b69 | 233 | int oddpar = 0; |
d3alek | 10:37e7c46837dc | 234 | |
d3alek | 0:94cffad90b69 | 235 | /* |
d3alek | 0:94cffad90b69 | 236 | */ |
d3alek | 0:94cffad90b69 | 237 | switch (work.bitcnt) { |
d3alek | 0:94cffad90b69 | 238 | case 0: |
d3alek | 0:94cffad90b69 | 239 | /* |
d3alek | 0:94cffad90b69 | 240 | * Start bit. |
d3alek | 0:94cffad90b69 | 241 | */ |
d3alek | 10:37e7c46837dc | 242 | int res = dat.read(); |
d3alek | 10:37e7c46837dc | 243 | if (res != 0) { |
d3alek | 10:37e7c46837dc | 244 | //printf("Illegal start bit condition. %d\n\r" + res); |
d3alek | 0:94cffad90b69 | 245 | } |
d3alek | 0:94cffad90b69 | 246 | work.bitcnt++; |
d3alek | 0:94cffad90b69 | 247 | break; |
d3alek | 0:94cffad90b69 | 248 | case 9: |
d3alek | 0:94cffad90b69 | 249 | /* |
d3alek | 0:94cffad90b69 | 250 | * Parity bit. |
d3alek | 0:94cffad90b69 | 251 | */ |
d3alek | 0:94cffad90b69 | 252 | for (int i = 0; i < 8; i++) { |
d3alek | 0:94cffad90b69 | 253 | if ((work.buffer[work.cEnd] & (1 << i)) != 0) { |
d3alek | 0:94cffad90b69 | 254 | oddpar++; |
d3alek | 0:94cffad90b69 | 255 | } |
d3alek | 0:94cffad90b69 | 256 | } |
d3alek | 0:94cffad90b69 | 257 | if (dat.read() == 1) { |
d3alek | 0:94cffad90b69 | 258 | oddpar++; |
d3alek | 0:94cffad90b69 | 259 | } |
d3alek | 0:94cffad90b69 | 260 | if ((oddpar % 2) != 1) { |
d3alek | 8:41b35bda9d48 | 261 | //printf("Data parity error.\n"); |
d3alek | 0:94cffad90b69 | 262 | } |
d3alek | 0:94cffad90b69 | 263 | work.bitcnt++; |
d3alek | 0:94cffad90b69 | 264 | break; |
d3alek | 0:94cffad90b69 | 265 | case 10: |
d3alek | 0:94cffad90b69 | 266 | /* |
d3alek | 0:94cffad90b69 | 267 | * Stop bit. |
d3alek | 0:94cffad90b69 | 268 | */ |
d3alek | 0:94cffad90b69 | 269 | if (dat.read() != 1) { |
d3alek | 8:41b35bda9d48 | 270 | //printf("Illegal stop bit condition.\n"); |
d3alek | 0:94cffad90b69 | 271 | } |
d3alek | 0:94cffad90b69 | 272 | if (work.cStart != ((work.cEnd + 1) % RINGBUFSIZ)) { |
d3alek | 0:94cffad90b69 | 273 | work.cEnd++; |
d3alek | 0:94cffad90b69 | 274 | work.cEnd = work.cEnd % RINGBUFSIZ; |
d3alek | 0:94cffad90b69 | 275 | work.bitcnt = 0; |
d3alek | 0:94cffad90b69 | 276 | } else { |
d3alek | 2:e35627187804 | 277 | init_work(); |
d3alek | 0:94cffad90b69 | 278 | printf("Buffer overrun.\n"); |
d3alek | 0:94cffad90b69 | 279 | } |
d3alek | 0:94cffad90b69 | 280 | break; |
d3alek | 0:94cffad90b69 | 281 | default: |
d3alek | 0:94cffad90b69 | 282 | if ((1 <= work.bitcnt) && (work.bitcnt <= 8)) { |
d3alek | 0:94cffad90b69 | 283 | /* |
d3alek | 0:94cffad90b69 | 284 | * data bit. |
d3alek | 0:94cffad90b69 | 285 | */ |
d3alek | 0:94cffad90b69 | 286 | if (dat.read() == 1) { |
d3alek | 0:94cffad90b69 | 287 | work.buffer[work.cEnd] |= (1 << (work.bitcnt - 1)); |
d3alek | 0:94cffad90b69 | 288 | } else { |
d3alek | 0:94cffad90b69 | 289 | work.buffer[work.cEnd] &= ~(1 << (work.bitcnt - 1)); |
d3alek | 0:94cffad90b69 | 290 | } |
d3alek | 0:94cffad90b69 | 291 | work.bitcnt++; |
d3alek | 0:94cffad90b69 | 292 | } else { |
d3alek | 0:94cffad90b69 | 293 | /* |
d3alek | 0:94cffad90b69 | 294 | * Illegal internal state. |
d3alek | 0:94cffad90b69 | 295 | */ |
d3alek | 8:41b35bda9d48 | 296 | //printf("Illegal internal state found.\n"); |
d3alek | 0:94cffad90b69 | 297 | init_work(); |
d3alek | 0:94cffad90b69 | 298 | } |
d3alek | 0:94cffad90b69 | 299 | break; |
d3alek | 0:94cffad90b69 | 300 | } |
d3alek | 0:94cffad90b69 | 301 | wdt.detach(); |
d3alek | 0:94cffad90b69 | 302 | wdt.attach_us(this, &PS2MS::func_timeout, 250); |
d3alek | 10:37e7c46837dc | 303 | mInFuncFall = false; |
d3alek | 0:94cffad90b69 | 304 | } |
d3alek | 0:94cffad90b69 | 305 | |
d3alek | 10:37e7c46837dc | 306 | void PS2MS::init_work(void) |
d3alek | 10:37e7c46837dc | 307 | { |
d3alek | 0:94cffad90b69 | 308 | work.bitcnt = 0; |
d3alek | 0:94cffad90b69 | 309 | work.cStart = 0; |
d3alek | 0:94cffad90b69 | 310 | work.cEnd = 0; |
d3alek | 0:94cffad90b69 | 311 | } |