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

Dependencies:   Servo mbed

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?

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