Aleksandar Kodzhabashev
/
TrackballQuery
An example of using polling PS/2 using the modified mbed PS/2 library
mylib/PS2/PS2MS.cpp
- Committer:
- d3alek
- Date:
- 2014-03-12
- Revision:
- 11:f5dcf8811a4e
- Parent:
- 10:37e7c46837dc
File content as of revision 11:f5dcf8811a4e:
/** * PS/2 mouse interface control class (Version 0.0.1) * * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) * http://shinta.main.jp/ */ #include "PS2MS.h" #define DEBUG false /** * Create. * * @param clk_pin Clock pin. * @param dat_pin Data pin. */ PS2MS::PS2MS(PinName clk_pin, PinName dat_pin) : clk(clk_pin), dat(dat_pin), clkOut(clk_pin), mSending(false), mInFuncFall(false) { init_work(); dat.input(); clk.fall(this, &PS2MS::func_fall); timeout = 1; } /** * Destory. */ PS2MS::~PS2MS() { wdt.detach(); } int PS2MS::getc() { tot.reset(); tot.start(); while (work.cStart == work.cEnd) { wait_ms(1); if ((timeout > 0) && (tot.read_ms() > timeout)) { return EOF; } } tot.stop(); char c = work.buffer[work.cStart++]; work.cStart = work.cStart % RINGBUFSIZ; return c; } int PS2MS::sendCommand(char c) { while (mInFuncFall) { continue; } mSending = true; if (DEBUG) printf("S "); dat.output(); clkOut.output(); clkOut.write(0); wait_us(200); dat.write(0); wait_us(10); clkOut.write(1); clkOut.input(); int parcnt = 0; for (int i = 0; i < 10; i++) { if (!waitClockDownEdge()) { mSending = false; wait_us(50); if (DEBUG) printf("R "); return -1; } if ((0 <= i) && (i <= 7)) { /* * Data bit. */ if ((c & (1 << i)) == 0) { dat.write(0); } else { dat.write(1); parcnt++; } } if (i == 8) { /* * Parity bit. */ if ((parcnt % 2) == 0) { dat.write(1); } else { dat.write(0); } } if (i == 9) { /* * Stop bit. */ dat.write(1); } } dat.input(); /* * Check a ACK. */ if (!waitClockDownEdge()) { mSending = false; wait_us(50); if (DEBUG) printf("R "); return -2; } if (dat.read() != 0) { mSending = false; wait_us(50); if (DEBUG) printf("R "); return -3; } if (!waitClockUpLevel()) { mSending = false; wait_us(50); if (DEBUG) printf("R "); return -4; } mSending = false; if (DEBUG) printf("E "); wait_us(50); return 0; } /** * Wait a clock up level. * * @return true if wait done. */ bool PS2MS::waitClockUpLevel(void) { int cnt; /* * Wait until clock is low. */ cnt = 0; clkOut.input(); while (clkOut.read() == 0) { cnt++; if (MAX_RETRY < cnt) { return false; } wait_us(1); } return true; } /** * Wait a clock down edge. * * @return true if wait done. */ bool PS2MS::waitClockDownEdge(void) { //tot.reset(); //tot.start(); //while (work.cStart == work.cEnd) { // if (tot.read_ms() > CLOCK_DOWN_EDGE_WAIT_MS) { // tot.stop(); // return false; // } //} //tot.stop(); // char c = work.buffer[work.cStart++]; //work.cStart = work.cStart % RINGBUFSIZ; //return c; int cnt; /* * Wait until clock is low. */ cnt = 0; clkOut.input(); while (clkOut.read() == 0) { cnt++; if (MAX_RETRY < cnt) { return false; } wait_us(1); } /* * Wait until clock is high. */ cnt = 0; while (clkOut.read() == 1) { cnt++; if (MAX_RETRY < cnt) { return false; } wait_us(1); } return true; } /** * Set timeout. * * @param ms Timeout ms. */ void PS2MS::setTimeout(int ms) { timeout = ms; } void PS2MS::func_timeout(void) { work.bitcnt = 0; } void PS2MS::func_fall(void) { if (mSending) { return; } mInFuncFall = true; int oddpar = 0; /* */ switch (work.bitcnt) { case 0: /* * Start bit. */ int res = dat.read(); if (res != 0) { //printf("Illegal start bit condition. %d\n\r" + res); } work.bitcnt++; break; case 9: /* * Parity bit. */ for (int i = 0; i < 8; i++) { if ((work.buffer[work.cEnd] & (1 << i)) != 0) { oddpar++; } } if (dat.read() == 1) { oddpar++; } if ((oddpar % 2) != 1) { //printf("Data parity error.\n"); } work.bitcnt++; break; case 10: /* * Stop bit. */ if (dat.read() != 1) { //printf("Illegal stop bit condition.\n"); } if (work.cStart != ((work.cEnd + 1) % RINGBUFSIZ)) { work.cEnd++; work.cEnd = work.cEnd % RINGBUFSIZ; work.bitcnt = 0; } else { init_work(); printf("Buffer overrun.\n"); } break; default: if ((1 <= work.bitcnt) && (work.bitcnt <= 8)) { /* * data bit. */ if (dat.read() == 1) { work.buffer[work.cEnd] |= (1 << (work.bitcnt - 1)); } else { work.buffer[work.cEnd] &= ~(1 << (work.bitcnt - 1)); } work.bitcnt++; } else { /* * Illegal internal state. */ //printf("Illegal internal state found.\n"); init_work(); } break; } wdt.detach(); wdt.attach_us(this, &PS2MS::func_timeout, 250); mInFuncFall = false; } void PS2MS::init_work(void) { work.bitcnt = 0; work.cStart = 0; work.cEnd = 0; }