An example of using polling PS/2 using the modified mbed PS/2 library

Dependencies:   Servo mbed

Committer:
d3alek
Date:
Wed Mar 19 18:44:49 2014 +0000
Revision:
14:168aa965b1b4
Parent:
11:f5dcf8811a4e
best achieved;

Who changed what in which revision?

UserRevisionLine numberNew 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 }