A version of the PS/2 library customized for MbedConsole. Also includes a few things that make it's behavior easier to control and a few bug fixes.
Fork of PS2 by
Revision 1:823c2798e398, committed 2010-09-29
- Comitter:
- shintamainjp
- Date:
- Wed Sep 29 14:11:44 2010 +0000
- Parent:
- 0:7ee6afa15d51
- Child:
- 2:a57bbbec16b1
- Commit message:
Changed in this revision
--- a/PS2.cpp Tue Aug 31 11:25:34 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,220 +0,0 @@ -/** - * PS/2 interface control class (Version 0.0.1) - * - * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) - * http://shinta.main.jp/ - */ - -#include "PS2.h" - -#define LOCK() sem.take() -#define UNLOCK() sem.release() - -PS2::PS2(PinName clkin_pin, PinName datin_pin, PinName clkout_pin, PinName datout_pin) - : - clkin(clkin_pin), datin(datin_pin), - clkout(clkout_pin), datout(datout_pin), - writepoint(0), readpoint(0) { - init_work(); - clkin.mode(PullUp); - datin.mode(PullUp); - clkin.fall(this, &PS2::func_fall); - - clkout.write(0); - datout.write(0); -} - -PS2::~PS2() { -} - -bool PS2::exists(void) { - LOCK(); - bool b = (readpoint == writepoint) ? false : true; - UNLOCK(); - return b; -} - -int PS2::getData(uint8_t *buf, size_t bufsiz) { - LOCK(); - - /* - * Check a buffer empty. - */ - if (readpoint == writepoint) { - UNLOCK(); - return -1; - } - - /* - * Check a storage buffer size. - */ - if (bufsiz < DATABUFSIZ) { - UNLOCK(); - return -2; - } - - /* - * Copy the data. - */ - const int nbytes = ringbuffer[readpoint].bytecnt; - for (int i = 0; i < nbytes; i++) { - buf[i] = ringbuffer[readpoint].buffer[i]; - } - - /* - * Increment read pointer. - */ - readpoint++; - if (RINGBUFSIZ <= readpoint) { - readpoint = 0; - } - - UNLOCK(); - return nbytes; -} - -void PS2::func_timeout(void) { - - LOCK(); - - /* - * Check a buffer full. - */ - const int n = ((readpoint - 1) < 0) ? (RINGBUFSIZ - 1) : (readpoint - 1); - if (n == writepoint) { - init_work(); - // printf("Buffer full.\n"); - UNLOCK(); - return; - } - - /* - * Check a data size. - */ - if (work.bytecnt == 0) { - init_work(); - // printf("Empty data detected.\n"); - UNLOCK(); - return; - } - - /* - * Check a error. - */ - if (work.errcnt > 0) { - init_work(); - // printf("Error detected.\n"); - UNLOCK(); - return; - } - - /* - * Copy the data. - */ - ringbuffer[writepoint].bytecnt = work.bytecnt; - for (int i = 0; i < work.bytecnt; i++) { - ringbuffer[writepoint].buffer[i] = work.buffer[i]; - } - - /* - * Increment write pointer. - */ - writepoint++; - if (RINGBUFSIZ <= writepoint) { - writepoint = 0; - } - - /* - * Reset variables for work. - */ - init_work(); - - UNLOCK(); -} - -void PS2::func_fall(void) { - - LOCK(); - - /* - */ - switch (work.bitcnt) { - case 0: - // start bit. - /* - */ - if (datin.read() != 0) { - // printf("Illegal start bit condition.\n"); - work.errcnt++; - } - /* - */ - work.bitcnt++; - break; - case 9: - // parity bit. - /* - */ - { - int oddpar = 0; - for (int i = 0; i < 8; i++) { - if ((work.buffer[work.bytecnt] & (1 << i)) != 0) { - oddpar++; - } - } - if (datin.read() == 1) { - oddpar++; - } - if ((oddpar % 2) != 1) { - // printf("Data parity error.\n"); - work.errcnt++; - } - } - /* - */ - work.bitcnt++; - break; - case 10: - // stop bit. - /* - */ - if (datin.read() != 1) { - // printf("Illegal stop bit condition.\n"); - work.errcnt++; - } - /* - */ - work.bytecnt++; - work.bitcnt = 0; - break; - default: - if ((1 <= work.bitcnt) && (work.bitcnt <= 8)) { - /* - * data bit. - */ - if (datin.read() == 1) { - work.buffer[work.bytecnt] |= (1 << (work.bitcnt - 1)); - } else { - work.buffer[work.bytecnt] &= ~(1 << (work.bitcnt - 1)); - } - work.bitcnt++; - } else { - /* - * Illegal internal state. - */ - // printf("Illegal internal state found.\n"); - init_work(); - } - break; - } - - UNLOCK(); - timeout.attach_us(this, &PS2::func_timeout, TIMEOUT_US); -} - -void PS2::init_work(void) { - work.state = Idle; - work.bitcnt = 0; - work.bytecnt = 0; - work.errcnt = 0; -}
--- a/PS2.h Tue Aug 31 11:25:34 2010 +0000 +++ b/PS2.h Wed Sep 29 14:11:44 2010 +0000 @@ -9,7 +9,6 @@ #define _PS2_H_ #include "mbed.h" -#include "Semaphore.h" /** * PS/2 interface control class. @@ -19,70 +18,29 @@ /** * Create. * - * @param clkinpin Input pin for clock. - * @param datinpin Input pin for data. + * @param clk_pin Clock pin. + * @param dat_pin Data pin. */ - PS2(PinName clkin_pin, PinName datin_pin, PinName clkout_pin = NC, PinName datout_pin = NC); + PS2(PinName clk_pin, PinName dat_pin); /** * Destory. */ - ~PS2(); - - /** - * Check exists a data. - * - * @return true if a data exists. - */ - bool exists(void); + virtual ~PS2(); /** - * Get a data into a buffer. + * Get a data from a PS/2 device. * - * @param buf A pointer to a buffer. - * @param bufsiz A size of the buffer. - * - * @return Number of a byte size. + * @return A data from a PS/2 device. */ - int getData(uint8_t *buf, size_t bufsiz); - -private: - InterruptIn clkin; - DigitalIn datin; - DigitalOut clkout; - DigitalOut datout; - Timeout timeout; - Semaphore sem; - int writepoint; - int readpoint; - static const int TIMEOUT_US = 10 * 1000; - static const int RINGBUFSIZ = 16; - static const int DATABUFSIZ = 32; + virtual int getc(void) = 0; - typedef enum { - Idle, - Reading, - Writing - } State; - - typedef struct { - State state; - int bitcnt; - int bytecnt; - int errcnt; - uint8_t buffer[DATABUFSIZ]; - } work_t; - work_t work; - - typedef struct { - int bytecnt; - uint8_t buffer[DATABUFSIZ]; - } data_t; - data_t ringbuffer[RINGBUFSIZ]; - - void func_timeout(void); - void func_fall(void); - void init_work(void); + /** + * Set timeout. + * + * @param ms Timeout ms. + */ + virtual void setTimeout(int ms) = 0; }; #endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PS2KB.cpp Wed Sep 29 14:11:44 2010 +0000 @@ -0,0 +1,140 @@ +/** + * PS/2 keyboard interface control class (Version 0.0.1) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ + +#include "PS2KB.h" + +/** + * Create. + * + * @param clk_pin Clock pin. + * @param dat_pin Data pin. + */ +PS2KB::PS2KB(PinName clk_pin, PinName dat_pin) + : clk(clk_pin), dat(dat_pin) { + init_work(); + clk.fall(this, &PS2KB::func_fall); + timeout = 1; +} + +/** + * Destory. + */ +PS2KB::~PS2KB() { + wdt.detach(); +} + +/** + * Get a data from a PS/2 device. + * + * @return A data from a PS/2 device. + */ +int PS2KB::getc() { + tot.reset(); + tot.start(); + while (work.cStart == work.cEnd) { + wait_ms(1); + if ((timeout > 0) && (tot.read_ms() > timeout)) { + // printf("Timeout occured.\n"); + return EOF; + } + } + tot.stop(); + + char c = work.buffer[work.cStart++]; + work.cStart = work.cStart % RINGBUFSIZ; + + return c; +} + +/** + * Set timeout. + * + * @param ms Timeout ms. + */ +void PS2KB::setTimeout(int ms) { + timeout = ms; +} + +void PS2KB::func_timeout(void) { + work.bitcnt = 0; +} + +void PS2KB::func_fall(void) { + int oddpar = 0; + /* + */ + switch (work.bitcnt) { + case 0: + /* + * Start bit. + */ + if (dat.read() != 0) { + // printf("Illegal start bit condition.\n"); + } + 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 { + // 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, &PS2KB::func_timeout, 250); +} + +void PS2KB::init_work(void) { + work.bitcnt = 0; + work.cStart = 0; + work.cEnd = 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PS2KB.h Wed Sep 29 14:11:44 2010 +0000 @@ -0,0 +1,67 @@ +/** + * PS/2 keyboard interface control class (Version 0.0.1) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ + +#ifndef _PS2KB_H_ +#define _PS2KB_H_ + +#include "mbed.h" + +/** + * PS/2 keyboard interface control class. + */ +class PS2KB { +public: + /** + * Create. + * + * @param clk_pin Clock pin. + * @param dat_pin Data pin. + */ + PS2KB(PinName clk_pin, PinName dat_pin); + + /** + * Destory. + */ + virtual ~PS2KB(); + + /** + * Get a data from a PS/2 device. + * + * @return A data from a PS/2 device. + */ + virtual int getc(void); + + /** + * Set timeout. + * + * @param ms Timeout ms. + */ + virtual void setTimeout(int ms); + +private: + static const int RINGBUFSIZ = 256; + InterruptIn clk; /**< Interrupt input for CLK. */ + DigitalIn dat; /**< Digital input for DAT. */ + Timeout wdt; /**< Watch dog timer. */ + Timer tot; /**< Timeout timer. */ + int timeout; /**< Timeout[ms] for getc(). */ + + typedef struct { + int bitcnt; + int cStart; + int cEnd; + uint8_t buffer[RINGBUFSIZ]; + } work_t; + work_t work; + + void func_timeout(void); + void func_fall(void); + + void init_work(void); +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PS2KB_INIT.cpp Wed Sep 29 14:11:44 2010 +0000 @@ -0,0 +1,233 @@ +/** + * PS/2 keyboard interface control class (Version 0.0.1) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ +#include "PS2KB_INIT.h" + +/** + * Create. + */ +PS2KB_INIT::PS2KB_INIT(PinName clk_pin, PinName dat_pin) + : clk(clk_pin), dat(dat_pin) { + clk.input(); + dat.input(); + clk.write(1); + dat.write(1); + + char txdat[12] = "\xFF\xED\x07\xF2\xED\x00\xF3\x20\xF3\x00\xF4"; + const int n = sizeof(txdat); + int txerrcnt = 0; + int rxerrcnt = 0; + for (int i = 0; i < n; i++) { + if (send(txdat[i]) != 0) { + txerrcnt++; + } + if (recv() < 0) { + rxerrcnt++; + } + if (txdat[i] == 0xF2) { + if (recv() < 0) { + rxerrcnt++; + } + } + } + + if (txerrcnt > 0) { + // printf("TX %d errors occured.\n", txerrcnt); + } + if (rxerrcnt > 0) { + // printf("RX %d errors occured.\n", rxerrcnt); + } +} + +/** + * Destroy. + */ +PS2KB_INIT::~PS2KB_INIT() { +} + +/** + * Send a byte data. + * + * @param c a character. + * + * @return Negative value is a error number. + */ +int PS2KB_INIT::send(uint8_t c) { + clk.output(); + dat.output(); + + clk.write(0); + wait_us(200); + + dat.write(0); + wait_us(10); + clk.write(1); + wait_us(10); + + clk.input(); + int parcnt = 0; + for (int i = 0; i < 10; i++) { + if (!waitClockDownEdge()) { + 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()) { + return -2; + } + if (dat.read() != 0) { + return -3; + } + + if (!waitClockUpLevel()) { + return -4; + } + + return 0; +} + +/** + * Receive a byte data. + * + * @return return a data. Negative value is a error number. + */ +int PS2KB_INIT::recv(void) { + uint8_t c = 0; + clk.input(); + dat.input(); + int parcnt = 0; + for (int i = 0; i < 11; i++) { + if (!waitClockDownEdge()) { + return -1; + } + if (i == 0) { + /* + * Start bit. + */ + if (dat.read() != 0) { + return -2; + } + } + if ((1 <= i) && (i <= 8)) { + /* + * Data bit. + */ + if (dat.read() == 0) { + c &= ~(1 << (i - 1)); + } else { + c |= (1 << (i - 1)); + parcnt++; + } + } + if (i == 9) { + /* + * Parity bit. + */ + if (dat.read() == 0) { + if ((parcnt % 2) != 1) { + return -3; + } + } else { + if ((parcnt % 2) != 0) { + return -4; + } + } + } + if (i == 10) { + /* + * Stop bit. + */ + if (dat.read() != 1) { + return -5; + } + } + } + return (int)c; +} + +/** + * Wait a clock down edge. + * + * @return true if wait done. + */ +bool PS2KB_INIT::waitClockDownEdge(void) { + int cnt; + /* + * Wait until clock is low. + */ + cnt = 0; + while (clk.read() == 0) { + cnt++; + if (MAX_RETRY < cnt) { + return false; + } + wait_us(1); + } + /* + * Wait until clock is high. + */ + cnt = 0; + while (clk.read() == 1) { + cnt++; + if (MAX_RETRY < cnt) { + return false; + } + wait_us(1); + } + return true; +} + +/** + * Wait a clock up level. + * + * @return true if wait done. + */ +bool PS2KB_INIT::waitClockUpLevel(void) { + int cnt; + /* + * Wait until clock is low. + */ + cnt = 0; + while (clk.read() == 0) { + cnt++; + if (MAX_RETRY < cnt) { + return false; + } + wait_us(1); + } + return true; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PS2KB_INIT.h Wed Sep 29 14:11:44 2010 +0000 @@ -0,0 +1,64 @@ +/** + * PS/2 keyboard interface control class (Version 0.0.1) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ +#ifndef _PS2KB_INIT_H_ +#define _PS2KB_INIT_H_ + +#include "mbed.h" + +/** + * PS2 keyboard initializer. + */ +class PS2KB_INIT { +public: + + /** + * Create. + */ + PS2KB_INIT(PinName clk_pin, PinName dat_pin); + + /** + * Destroy. + */ + ~PS2KB_INIT(); +private: + DigitalInOut clk; + DigitalInOut dat; + + static const int MAX_RETRY = 1000000; + + /** + * Send a byte data. + * + * @param c a character. + * + * @return Negative value is a error number. + */ + int send(uint8_t c); + + /** + * Receive a byte data. + * + * @return return a data. Negative value is a error number. + */ + int recv(void); + + /** + * Wait a clock down edge. + * + * @return true if wait done. + */ + bool waitClockDownEdge(void); + + /** + * Wait a clock up level. + * + * @return true if wait done. + */ + bool waitClockUpLevel(void); +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PS2Keyboard.cpp Wed Sep 29 14:11:44 2010 +0000 @@ -0,0 +1,117 @@ +/** + * PS/2 keyboard interface control class (Version 0.0.1) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ +#include "PS2Keyboard.h" + +PS2Keyboard::PS2Keyboard(PinName clk_pin, PinName dat_pin) + : ps2kb_init(clk_pin, dat_pin), ps2kb(clk_pin, dat_pin) { +} + +PS2Keyboard::~PS2Keyboard() { +} + +bool PS2Keyboard::processing(keyboard_event_t *p) { + bool emit = false; + const int c = ps2kb.getc(); + if (0 <= c) { + scancode[count++] = c; + switch (count) { + case 1: + if ((scancode[0] != 0xE0) + && (scancode[0] != 0xE1) + && (scancode[0] != 0xF0)) { + p->type = KeyMake; + p->length = count; + memcpy(p->scancode, scancode, sizeof(p->scancode)); + emit = true; + count = 0; + } + break; + case 2: + if (scancode[0] == 0xF0) { + p->type = KeyBreak; + p->length = count; + memcpy(p->scancode, scancode, sizeof(p->scancode)); + emit = true; + count = 0; + } + if ((scancode[0] == 0xE0) + && (scancode[1] != 0xF0) + && (scancode[1] != 0x12)) { + p->type = KeyMake; + p->length = count; + memcpy(p->scancode, scancode, sizeof(p->scancode)); + emit = true; + count = 0; + } + break; + case 3: + if ((scancode[0] == 0xE0) + && (scancode[1] == 0xF0) + && (scancode[2] != 0x7C)) { + p->type = KeyBreak; + p->length = count; + memcpy(p->scancode, scancode, sizeof(p->scancode)); + emit = true; + count = 0; + } + break; + case 4: + if ((scancode[0] == 0xE0) + && (scancode[1] == 0x12) + && (scancode[2] == 0xE0) + && (scancode[3] == 0x7C)) { + p->type = KeyMake; + p->length = count; + memcpy(p->scancode, scancode, sizeof(p->scancode)); + emit = true; + count = 0; + } + break; + case 5: + // Do nothing. + break; + case 6: + if ((scancode[0] == 0xE0) + && (scancode[1] == 0xF0) + && (scancode[2] == 0x7C) + && (scancode[3] == 0xE0) + && (scancode[4] == 0xF0) + && (scancode[5] == 0x12)) { + p->type = KeyBreak; + p->length = count; + memcpy(p->scancode, scancode, sizeof(p->scancode)); + emit = true; + count = 0; + } + break; + case 7: + // Do nothing. + break; + case 8: + if ((scancode[0] == 0xE1) + && (scancode[1] == 0x14) + && (scancode[2] == 0x77) + && (scancode[3] == 0xE1) + && (scancode[4] == 0xF0) + && (scancode[5] == 0x14) + && (scancode[6] == 0xF0) + && (scancode[7] == 0x77)) { + p->type = KeyMake; + p->length = count; + memcpy(p->scancode, scancode, sizeof(p->scancode)); + emit = true; + count = 0; + } + break; + default: + count = 0; + break; + } + count = count % sizeof(scancode); + } + return emit; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PS2Keyboard.h Wed Sep 29 14:11:44 2010 +0000 @@ -0,0 +1,34 @@ +/** + * PS/2 keyboard interface control class (Version 0.0.1) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ +#ifndef _PS2_KEYBOARD_H_ +#define _PS2_KEYBOARD_H_ + +#include "PS2KB_INIT.h" +#include "PS2KB.h" + +class PS2Keyboard { +public: + PS2Keyboard(PinName clk_pin, PinName dat_pin); + ~PS2Keyboard(); + typedef enum { + KeyMake, + KeyBreak + } Type; + typedef struct { + Type type; + int length; + char scancode[8]; + } keyboard_event_t; + bool processing(keyboard_event_t *p); +private: + PS2KB_INIT ps2kb_init; + PS2KB ps2kb; + int count; + char scancode[8]; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PS2MS.cpp Wed Sep 29 14:11:44 2010 +0000 @@ -0,0 +1,135 @@ +/** + * PS/2 mouse interface control class (Version 0.0.1) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ + +#include "PS2MS.h" + +/** + * 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) { + init_work(); + 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)) { + // printf("Timeout occured.\n"); + return EOF; + } + } + tot.stop(); + + char c = work.buffer[work.cStart++]; + work.cStart = work.cStart % RINGBUFSIZ; + + return c; +} + +/** + * 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) { + int oddpar = 0; + /* + */ + switch (work.bitcnt) { + case 0: + /* + * Start bit. + */ + if (dat.read() != 0) { + // printf("Illegal start bit condition.\n"); + } + 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 { + // 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); +} + +void PS2MS::init_work(void) { + work.bitcnt = 0; + work.cStart = 0; + work.cEnd = 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PS2MS.h Wed Sep 29 14:11:44 2010 +0000 @@ -0,0 +1,67 @@ +/** + * PS/2 mouse interface control class (Version 0.0.1) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ + +#ifndef _PS2MS_H_ +#define _PS2MS_H_ + +#include "mbed.h" + +/** + * PS/2 mouse interface control class. + */ +class PS2MS { +public: + /** + * Create. + * + * @param clk_pin Clock pin. + * @param dat_pin Data pin. + */ + PS2MS(PinName clk_pin, PinName dat_pin); + + /** + * Destory. + */ + virtual ~PS2MS(); + + /** + * Get a data from a PS/2 device. + * + * @return A data from a PS/2 device. + */ + virtual int getc(void); + + /** + * Set timeout. + * + * @param ms Timeout ms. + */ + virtual void setTimeout(int ms); + +private: + static const int RINGBUFSIZ = 512; + InterruptIn clk; /**< Interrupt input for CLK. */ + DigitalIn dat; /**< Digital input for DAT. */ + Timeout wdt; /**< Watch dog timer. */ + Timer tot; /**< Timeout timer. */ + int timeout; /**< Timeout[ms] for getc(). */ + + typedef struct { + int bitcnt; + int cStart; + int cEnd; + uint8_t buffer[RINGBUFSIZ]; + } work_t; + work_t work; + + void func_timeout(void); + void func_fall(void); + + void init_work(void); +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PS2MS_INIT.cpp Wed Sep 29 14:11:44 2010 +0000 @@ -0,0 +1,236 @@ +/** + * PS/2 mouse interface control class (Version 0.0.1) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ +#include "PS2MS_INIT.h" + +/** + * Create. + */ +PS2MS_INIT::PS2MS_INIT(PinName clk_pin, PinName dat_pin) + : clk(clk_pin), dat(dat_pin) { + clk.input(); + dat.input(); + clk.write(1); + dat.write(1); + + char txdat[17] = "\xFF\xFF\xFF\xF3\xC8\xF3\x64\xF3\x50\xF2\xE8\x03\xE6\xF3\x28\xF4"; + const int n = sizeof(txdat); + int txerrcnt = 0; + int rxerrcnt = 0; + for (int i = 0; i < n; i++) { + if (send(txdat[i]) != 0) { + txerrcnt++; + } + if (recv() < 0) { + rxerrcnt++; + } + if (txdat[i] == 0xFF) { + if (recv() < 0) { + rxerrcnt++; + } + if (recv() < 0) { + rxerrcnt++; + } + } + } + + if (txerrcnt > 0) { + // printf("TX %d errors occured.\n", txerrcnt); + } + if (rxerrcnt > 0) { + // printf("RX %d errors occured.\n", rxerrcnt); + } +} + +/** + * Destroy. + */ +PS2MS_INIT::~PS2MS_INIT() { +} + +/** + * Send a byte data. + * + * @param c a character. + * + * @return Negative value is a error number. + */ +int PS2MS_INIT::send(uint8_t c) { + clk.output(); + dat.output(); + + clk.write(0); + wait_us(200); + + dat.write(0); + wait_us(10); + clk.write(1); + wait_us(10); + + clk.input(); + int parcnt = 0; + for (int i = 0; i < 10; i++) { + if (!waitClockDownEdge()) { + 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()) { + return -2; + } + if (dat.read() != 0) { + return -3; + } + + if (!waitClockUpLevel()) { + return -4; + } + + return 0; +} + +/** + * Receive a byte data. + * + * @return return a data. Negative value is a error number. + */ +int PS2MS_INIT::recv(void) { + uint8_t c = 0; + clk.input(); + dat.input(); + int parcnt = 0; + for (int i = 0; i < 11; i++) { + if (!waitClockDownEdge()) { + return -1; + } + if (i == 0) { + /* + * Start bit. + */ + if (dat.read() != 0) { + return -2; + } + } + if ((1 <= i) && (i <= 8)) { + /* + * Data bit. + */ + if (dat.read() == 0) { + c &= ~(1 << (i - 1)); + } else { + c |= (1 << (i - 1)); + parcnt++; + } + } + if (i == 9) { + /* + * Parity bit. + */ + if (dat.read() == 0) { + if ((parcnt % 2) != 1) { + return -3; + } + } else { + if ((parcnt % 2) != 0) { + return -4; + } + } + } + if (i == 10) { + /* + * Stop bit. + */ + if (dat.read() != 1) { + return -5; + } + } + } + return (int)c; +} + +/** + * Wait a clock down edge. + * + * @return true if wait done. + */ +bool PS2MS_INIT::waitClockDownEdge(void) { + int cnt; + /* + * Wait until clock is low. + */ + cnt = 0; + while (clk.read() == 0) { + cnt++; + if (MAX_RETRY < cnt) { + return false; + } + wait_us(1); + } + /* + * Wait until clock is high. + */ + cnt = 0; + while (clk.read() == 1) { + cnt++; + if (MAX_RETRY < cnt) { + return false; + } + wait_us(1); + } + return true; +} + +/** + * Wait a clock up level. + * + * @return true if wait done. + */ +bool PS2MS_INIT::waitClockUpLevel(void) { + int cnt; + /* + * Wait until clock is low. + */ + cnt = 0; + while (clk.read() == 0) { + cnt++; + if (MAX_RETRY < cnt) { + return false; + } + wait_us(1); + } + return true; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PS2MS_INIT.h Wed Sep 29 14:11:44 2010 +0000 @@ -0,0 +1,64 @@ +/** + * PS/2 mouse interface control class (Version 0.0.1) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ +#ifndef _PS2MS_INIT_H_ +#define _PS2MS_INIT_H_ + +#include "mbed.h" + +/** + * PS2 mouse initializer. + */ +class PS2MS_INIT { +public: + + /** + * Create. + */ + PS2MS_INIT(PinName clk_pin, PinName dat_pin); + + /** + * Destroy. + */ + ~PS2MS_INIT(); +private: + DigitalInOut clk; + DigitalInOut dat; + + static const int MAX_RETRY = 1000000; + + /** + * Send a byte data. + * + * @param c a character. + * + * @return Negative value is a error number. + */ + int send(uint8_t c); + + /** + * Receive a byte data. + * + * @return return a data. Negative value is a error number. + */ + int recv(void); + + /** + * Wait a clock down edge. + * + * @return true if wait done. + */ + bool waitClockDownEdge(void); + + /** + * Wait a clock up level. + * + * @return true if wait done. + */ + bool waitClockUpLevel(void); +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PS2Mouse.cpp Wed Sep 29 14:11:44 2010 +0000 @@ -0,0 +1,55 @@ +/** + * PS/2 mouse interface control class (Version 0.0.1) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ +#include "PS2Mouse.h" + +PS2Mouse::PS2Mouse(PinName clk_pin, PinName dat_pin) + : ps2ms_init(clk_pin, dat_pin), ps2ms(clk_pin, dat_pin) { + cnt = 0; +} + +PS2Mouse::~PS2Mouse() { +} + +bool PS2Mouse::processing(mouse_event_t *p) { + bool emit = false; + const int c = ps2ms.getc(); + if (0 <= c) { + switch (cnt % 4) { + case 0: + mi.byte1.byte = c; + break; + case 1: + mi.byte2.byte = c; + break; + case 2: + mi.byte3.byte = c; + break; + case 3: + mi.byte4.byte = c; +#if 0 + printf("[%c:%c:%c] - (%4d,%4d) - <%d:%3d>\n", + mi.byte1.bit.btnLeft ? 'o' : ' ', + mi.byte1.bit.btnMiddle ? 'o' : ' ', + mi.byte1.bit.btnRight ? 'o' : ' ', + mi.byte1.bit.signX ? (-256 + mi.byte2.byte) : mi.byte2.byte, + mi.byte1.bit.signY ? (-256 + mi.byte3.byte) : mi.byte3.byte, + mi.byte4.bit.signZ, + mi.byte4.bit.signZ ? (-128 + mi.byte4.bit.value) : mi.byte4.bit.value); +#endif + p->left = mi.byte1.bit.btnLeft ? true : false; + p->center = mi.byte1.bit.btnCenter ? true : false; + p->right = mi.byte1.bit.btnRight ? true : false; + p->x = mi.byte1.bit.signX ? (-256 + mi.byte2.byte) : mi.byte2.byte; + p->y = mi.byte1.bit.signY ? (-256 + mi.byte3.byte) : mi.byte3.byte; + p->z = mi.byte4.bit.signZ ? (-128 + mi.byte4.bit.value) : mi.byte4.bit.value; + emit = true; + break; + } + cnt++; + } + return emit; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PS2Mouse.h Wed Sep 29 14:11:44 2010 +0000 @@ -0,0 +1,61 @@ +/** + * PS/2 mouse interface control class (Version 0.0.1) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ +#ifndef _PS2_MOUSE_H_ +#define _PS2_MOUSE_H_ + +#include "PS2MS_INIT.h" +#include "PS2MS.h" + +class PS2Mouse { +public: + PS2Mouse(PinName clk_pin, PinName dat_pin); + ~PS2Mouse(); + typedef struct { + bool left; + bool center; + bool right; + int x; + int y; + int z; + } mouse_event_t; + bool processing(mouse_event_t *p); +private: + PS2MS_INIT ps2ms_init; + PS2MS ps2ms; + typedef struct { + union { + uint8_t byte; + struct { + uint8_t btnLeft:1; + uint8_t btnRight:1; + uint8_t btnCenter:1; + uint8_t always1:1; + uint8_t signX:1; + uint8_t signY:1; + uint8_t overflowX:1; + uint8_t overflowY:1; + } bit; + } byte1; + union { + uint8_t byte; + } byte2; + union { + uint8_t byte; + } byte3; + union { + uint8_t byte; + struct { + uint8_t value:7; + uint8_t signZ:1; + } bit; + } byte4; + } mouse_info_t; + mouse_info_t mi; + int cnt; +}; + +#endif
--- a/Semaphore.h Tue Aug 31 11:25:34 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -#ifndef _SEMAPHORE_H_ -#define _SEMAPHORE_H_ - -/* - * http://mbed.org/forum/mbed/topic/181/#comment-799 - */ - -class Semaphore { -public: - Semaphore(): s(SemFree) {} - - bool take(bool block = true) { - int oldval; - do { - oldval = __ldrex(&s); - } while ((block && oldval == SemTaken) || __strex(SemTaken, &s) != 0); - if (!block) { - __clrex(); - } - return (oldval == SemFree); - } - - void release() { - s = SemFree; - } - -private: - enum { SemFree, SemTaken }; - int s; -}; - -#endif \ No newline at end of file