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