A test program for PS2 library.

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
shintamainjp
Date:
Wed Oct 13 10:50:55 2010 +0000
Parent:
3:a3ba8d3e3958
Commit message:
First version.

Changed in this revision

PS2.lib Show diff for this revision Revisions of this file
TextLCD.lib Show diff for this revision Revisions of this file
extlib/TextLCD.lib Show annotated file Show diff for this revision Revisions of this file
mylib/PS2/PS2.h Show annotated file Show diff for this revision Revisions of this file
mylib/PS2/PS2KB.cpp Show annotated file Show diff for this revision Revisions of this file
mylib/PS2/PS2KB.h Show annotated file Show diff for this revision Revisions of this file
mylib/PS2/PS2KB_INIT.cpp Show annotated file Show diff for this revision Revisions of this file
mylib/PS2/PS2KB_INIT.h Show annotated file Show diff for this revision Revisions of this file
mylib/PS2/PS2Keyboard.cpp Show annotated file Show diff for this revision Revisions of this file
mylib/PS2/PS2Keyboard.h Show annotated file Show diff for this revision Revisions of this file
mylib/PS2/PS2MS.cpp Show annotated file Show diff for this revision Revisions of this file
mylib/PS2/PS2MS.h Show annotated file Show diff for this revision Revisions of this file
mylib/PS2/PS2MS_INIT.cpp Show annotated file Show diff for this revision Revisions of this file
mylib/PS2/PS2MS_INIT.h Show annotated file Show diff for this revision Revisions of this file
mylib/PS2/PS2Mouse.cpp Show annotated file Show diff for this revision Revisions of this file
mylib/PS2/PS2Mouse.h Show annotated file Show diff for this revision Revisions of this file
--- a/PS2.lib	Wed Sep 29 22:15:15 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://mbed.org/users/shintamainjp/code/PS2/#a57bbbec16b1
--- a/TextLCD.lib	Wed Sep 29 22:15:15 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://mbed.org/users/simon/code/TextLCD/#44f34c09bd37
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extlib/TextLCD.lib	Wed Oct 13 10:50:55 2010 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/simon/code/TextLCD/#a53b3e2d6f1e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mylib/PS2/PS2.h	Wed Oct 13 10:50:55 2010 +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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mylib/PS2/PS2KB.cpp	Wed Oct 13 10:50:55 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/mylib/PS2/PS2KB.h	Wed Oct 13 10:50:55 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/mylib/PS2/PS2KB_INIT.cpp	Wed Oct 13 10:50:55 2010 +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;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mylib/PS2/PS2KB_INIT.h	Wed Oct 13 10:50:55 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/mylib/PS2/PS2Keyboard.cpp	Wed Oct 13 10:50:55 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/mylib/PS2/PS2Keyboard.h	Wed Oct 13 10:50:55 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/mylib/PS2/PS2MS.cpp	Wed Oct 13 10:50:55 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/mylib/PS2/PS2MS.h	Wed Oct 13 10:50:55 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 = 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mylib/PS2/PS2MS_INIT.cpp	Wed Oct 13 10:50:55 2010 +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;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mylib/PS2/PS2MS_INIT.h	Wed Oct 13 10:50:55 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/mylib/PS2/PS2Mouse.cpp	Wed Oct 13 10:50:55 2010 +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;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mylib/PS2/PS2Mouse.h	Wed Oct 13 10:50:55 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