PS/2 Keyboard
Revision 0:62b62530a82f, committed 2012-10-11
- Comitter:
- pprasad7
- Date:
- Thu Oct 11 20:15:09 2012 +0000
- Commit message:
- PS/2 Input;
Changed in this revision
diff -r 000000000000 -r 62b62530a82f PS2.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PS2.h Thu Oct 11 20:15:09 2012 +0000 @@ -0,0 +1,46 @@ +/** + * PS/2 interface control class (Version 0.0.1) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ + +#ifndef _PS2_H_ +#define _PS2_H_ + +#include "mbed.h" + +/** + * PS/2 interface control class. + */ +class PS2 { +public: + /** + * Create. + * + * @param clk_pin Clock pin. + * @param dat_pin Data pin. + */ + PS2(PinName clk_pin, PinName dat_pin); + + /** + * Destory. + */ + virtual ~PS2(); + + /** + * Get a data from a PS/2 device. + * + * @return A data from a PS/2 device. + */ + virtual int getc(void) = 0; + + /** + * Set timeout. + * + * @param ms Timeout ms. + */ + virtual void setTimeout(int ms) = 0; +}; + +#endif
diff -r 000000000000 -r 62b62530a82f PS2KB.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PS2KB.cpp Thu Oct 11 20:15:09 2012 +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; +}
diff -r 000000000000 -r 62b62530a82f PS2KB.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PS2KB.h Thu Oct 11 20:15:09 2012 +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
diff -r 000000000000 -r 62b62530a82f PS2KB_INIT.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PS2KB_INIT.cpp Thu Oct 11 20:15:09 2012 +0000 @@ -0,0 +1,240 @@ +/** + * 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); + + /* + * 0xFF: Reset. + * 0xED: Set/Reset status indicators. + * 0xF2: Read ID. + * 0xF3: Set typematic rate/delay. + * 0xF4: Enable. + */ + 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; +}
diff -r 000000000000 -r 62b62530a82f PS2KB_INIT.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PS2KB_INIT.h Thu Oct 11 20:15:09 2012 +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
diff -r 000000000000 -r 62b62530a82f PS2Keyboard.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PS2Keyboard.cpp Thu Oct 11 20:15:09 2012 +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; +}
diff -r 000000000000 -r 62b62530a82f PS2Keyboard.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PS2Keyboard.h Thu Oct 11 20:15:09 2012 +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
diff -r 000000000000 -r 62b62530a82f PS2MS.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PS2MS.cpp Thu Oct 11 20:15:09 2012 +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; +}
diff -r 000000000000 -r 62b62530a82f PS2MS.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PS2MS.h Thu Oct 11 20:15:09 2012 +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 = 1024; + 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
diff -r 000000000000 -r 62b62530a82f PS2MS_INIT.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PS2MS_INIT.cpp Thu Oct 11 20:15:09 2012 +0000 @@ -0,0 +1,249 @@ +/** + * 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); + + /* + * 0xFF: Reset command. + * 0xF3: Set sample rate. + * 0xF2: Read device type. + * 0xE8: Set resolution. + * 0xE6: Set scaling. + * 0xF4: Enable device. + */ + 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] == 0xF2) { + 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; +}
diff -r 000000000000 -r 62b62530a82f PS2MS_INIT.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PS2MS_INIT.h Thu Oct 11 20:15:09 2012 +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
diff -r 000000000000 -r 62b62530a82f PS2Mouse.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PS2Mouse.cpp Thu Oct 11 20:15:09 2012 +0000 @@ -0,0 +1,58 @@ +/** + * 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; + for (int i = 0; i < 4; i++) { + const int c = ps2ms.getc(); + if (0 <= c) { + switch (cnt % 4) { + case 0: + mi.byte1.byte = c; + /* + * Check and reset a buffer if state is wrong. + */ + if (mi.byte1.bit.always1 == 0) { + cnt = 0; + while (0 <= ps2ms.getc()) { + } + } + break; + case 1: + mi.byte2.byte = c; + break; + case 2: + mi.byte3.byte = c; + break; + case 3: + mi.byte4.byte = c; + /* + * Store a event data. + */ + 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; +}
diff -r 000000000000 -r 62b62530a82f PS2Mouse.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PS2Mouse.h Thu Oct 11 20:15:09 2012 +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