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.

Dependents:   MbedConsole

Fork of PS2 by Shinichiro Nakamura

Files at this revision

API Documentation at this revision

Comitter:
shintamainjp
Date:
Wed Sep 29 14:11:44 2010 +0000
Parent:
0:7ee6afa15d51
Child:
2:a57bbbec16b1
Commit message:

Changed in this revision

PS2.cpp Show diff for this revision Revisions of this file
PS2.h Show annotated file Show diff for this revision Revisions of this file
PS2KB.cpp Show annotated file Show diff for this revision Revisions of this file
PS2KB.h Show annotated file Show diff for this revision Revisions of this file
PS2KB_INIT.cpp Show annotated file Show diff for this revision Revisions of this file
PS2KB_INIT.h Show annotated file Show diff for this revision Revisions of this file
PS2Keyboard.cpp Show annotated file Show diff for this revision Revisions of this file
PS2Keyboard.h Show annotated file Show diff for this revision Revisions of this file
PS2MS.cpp Show annotated file Show diff for this revision Revisions of this file
PS2MS.h Show annotated file Show diff for this revision Revisions of this file
PS2MS_INIT.cpp Show annotated file Show diff for this revision Revisions of this file
PS2MS_INIT.h Show annotated file Show diff for this revision Revisions of this file
PS2Mouse.cpp Show annotated file Show diff for this revision Revisions of this file
PS2Mouse.h Show annotated file Show diff for this revision Revisions of this file
Semaphore.h Show diff for this revision Revisions of this file
--- 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