SG12864A

Dependents:   SG12864A_TestProgram

Revision:
5:4d86043f7942
Parent:
4:200d1ea4e76e
--- a/SG12864A.cpp	Tue Aug 10 12:36:05 2010 +0000
+++ b/SG12864A.cpp	Tue Aug 10 12:52:53 2010 +0000
@@ -1,528 +1,523 @@
-/**
- * SG12864A Graphics LCD module driver class (Version 0.0.1)
- *
- * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems)
- * http://shinta.main.jp/
- *
- * See also ...
- * http://mbed.org/users/shintamainjp/notebook/sg12864asunlike-display-graphics-lcd-driver/
- */
-
-#include "SG12864A.h"
-
-#define setPixel(x,y) buffer[((COLUMNS * 2)* ((y) / 8)) + (x)] |= (1 << ((y) % 8))
-#define unsetPixel(x,y) buffer[((COLUMNS * 2)* ((y) / 8)) + (x)] &= ~(1 << ((y) % 8))
-#define swap(a,b) {int c=a;a=b;b=c;}
-
-const uint8_t SG12864A::font5x7_data[] = {
-    0x00, 0x00, 0x00, 0x00, 0x00, // (white space)
-    0x00, 0x00, 0x5F, 0x00, 0x00, // !
-    0x00, 0x07, 0x00, 0x07, 0x00, // "
-    0x14, 0x7F, 0x14, 0x7F, 0x14, // #
-    0x24, 0x2A, 0x7F, 0x2A, 0x12, // $
-    0x23, 0x13, 0x08, 0x64, 0x62, // %
-    0x36, 0x49, 0x55, 0x22, 0x50, // &
-    0x00, 0x05, 0x03, 0x00, 0x00, // '
-    0x00, 0x1C, 0x22, 0x41, 0x00, // (
-    0x00, 0x41, 0x22, 0x1C, 0x00, // )
-    0x08, 0x2A, 0x1C, 0x2A, 0x08, // *
-    0x08, 0x08, 0x3E, 0x08, 0x08, // +
-    0x00, 0x50, 0x30, 0x00, 0x00, // ,
-    0x08, 0x08, 0x08, 0x08, 0x08, // -
-    0x00, 0x60, 0x60, 0x00, 0x00, // .
-    0x20, 0x10, 0x08, 0x04, 0x02, // /
-    0x3E, 0x51, 0x49, 0x45, 0x3E, // 0
-    0x00, 0x42, 0x7F, 0x40, 0x00, // 1
-    0x42, 0x61, 0x51, 0x49, 0x46, // 2
-    0x21, 0x41, 0x45, 0x4B, 0x31, // 3
-    0x18, 0x14, 0x12, 0x7F, 0x10, // 4
-    0x27, 0x45, 0x45, 0x45, 0x39, // 5
-    0x3C, 0x4A, 0x49, 0x49, 0x30, // 6
-    0x01, 0x71, 0x09, 0x05, 0x03, // 7
-    0x36, 0x49, 0x49, 0x49, 0x36, // 8
-    0x06, 0x49, 0x49, 0x29, 0x1E, // 9
-    0x00, 0x36, 0x36, 0x00, 0x00, // :
-    0x00, 0x56, 0x36, 0x00, 0x00, // ;
-    0x00, 0x08, 0x14, 0x22, 0x41, // <
-    0x14, 0x14, 0x14, 0x14, 0x14, // =
-    0x41, 0x22, 0x14, 0x08, 0x00, // >
-    0x02, 0x01, 0x51, 0x09, 0x06, // ?
-    0x32, 0x49, 0x79, 0x41, 0x3E, // @
-    0x7E, 0x11, 0x11, 0x11, 0x7E, // A
-    0x7F, 0x49, 0x49, 0x49, 0x36, // B
-    0x3E, 0x41, 0x41, 0x41, 0x22, // C
-    0x7F, 0x41, 0x41, 0x22, 0x1C, // D
-    0x7F, 0x49, 0x49, 0x49, 0x41, // E
-    0x7F, 0x09, 0x09, 0x01, 0x01, // F
-    0x3E, 0x41, 0x41, 0x51, 0x32, // G
-    0x7F, 0x08, 0x08, 0x08, 0x7F, // H
-    0x00, 0x41, 0x7F, 0x41, 0x00, // I
-    0x20, 0x40, 0x41, 0x3F, 0x01, // J
-    0x7F, 0x08, 0x14, 0x22, 0x41, // K
-    0x7F, 0x40, 0x40, 0x40, 0x40, // L
-    0x7F, 0x02, 0x04, 0x02, 0x7F, // M
-    0x7F, 0x04, 0x08, 0x10, 0x7F, // N
-    0x3E, 0x41, 0x41, 0x41, 0x3E, // O
-    0x7F, 0x09, 0x09, 0x09, 0x06, // P
-    0x3E, 0x41, 0x51, 0x21, 0x5E, // Q
-    0x7F, 0x09, 0x19, 0x29, 0x46, // R
-    0x46, 0x49, 0x49, 0x49, 0x31, // S
-    0x01, 0x01, 0x7F, 0x01, 0x01, // T
-    0x3F, 0x40, 0x40, 0x40, 0x3F, // U
-    0x1F, 0x20, 0x40, 0x20, 0x1F, // V
-    0x7F, 0x20, 0x18, 0x20, 0x7F, // W
-    0x63, 0x14, 0x08, 0x14, 0x63, // X
-    0x03, 0x04, 0x78, 0x04, 0x03, // Y
-    0x61, 0x51, 0x49, 0x45, 0x43, // Z
-    0x00, 0x00, 0x7F, 0x41, 0x41, // [
-    0x02, 0x04, 0x08, 0x10, 0x20, // /
-    0x41, 0x41, 0x7F, 0x00, 0x00, // ]
-    0x04, 0x02, 0x01, 0x02, 0x04, // ^
-    0x40, 0x40, 0x40, 0x40, 0x40, // _
-    0x00, 0x01, 0x02, 0x04, 0x00, // `
-    0x20, 0x54, 0x54, 0x54, 0x78, // a
-    0x7F, 0x48, 0x44, 0x44, 0x38, // b
-    0x38, 0x44, 0x44, 0x44, 0x20, // c
-    0x38, 0x44, 0x44, 0x48, 0x7F, // d
-    0x38, 0x54, 0x54, 0x54, 0x18, // e
-    0x08, 0x7E, 0x09, 0x01, 0x02, // f
-    0x08, 0x14, 0x54, 0x54, 0x3C, // g
-    0x7F, 0x08, 0x04, 0x04, 0x78, // h
-    0x00, 0x44, 0x7D, 0x40, 0x00, // i
-    0x20, 0x40, 0x44, 0x3D, 0x00, // j
-    0x00, 0x7F, 0x10, 0x28, 0x44, // k
-    0x00, 0x41, 0x7F, 0x40, 0x00, // l
-    0x7C, 0x04, 0x18, 0x04, 0x78, // m
-    0x7C, 0x08, 0x04, 0x04, 0x78, // n
-    0x38, 0x44, 0x44, 0x44, 0x38, // o
-    0x7C, 0x14, 0x14, 0x14, 0x08, // p
-    0x08, 0x14, 0x14, 0x18, 0x7C, // q
-    0x7C, 0x08, 0x04, 0x04, 0x08, // r
-    0x48, 0x54, 0x54, 0x54, 0x20, // s
-    0x04, 0x3F, 0x44, 0x40, 0x20, // t
-    0x3C, 0x40, 0x40, 0x20, 0x7C, // u
-    0x1C, 0x20, 0x40, 0x20, 0x1C, // v
-    0x3C, 0x40, 0x30, 0x40, 0x3C, // w
-    0x44, 0x28, 0x10, 0x28, 0x44, // x
-    0x0C, 0x50, 0x50, 0x50, 0x3C, // y
-    0x44, 0x64, 0x54, 0x4C, 0x44, // z
-    0x00, 0x08, 0x36, 0x41, 0x00, // {
-    0x00, 0x00, 0x7F, 0x00, 0x00, // |
-    0x00, 0x41, 0x36, 0x08, 0x00, // }
-    0x08, 0x08, 0x2A, 0x1C, 0x08, // ->
-    0x08, 0x1C, 0x2A, 0x08, 0x08  // <-
-};
-
-SG12864A::SG12864A(PinName di,
-                   PinName rw,
-                   PinName en,
-                   PinName db0,
-                   PinName db1,
-                   PinName db2,
-                   PinName db3,
-                   PinName db4,
-                   PinName db5,
-                   PinName db6,
-                   PinName db7,
-                   PinName cs1,
-                   PinName cs2,
-                   PinName res)
-        :
-        ioDI(di),
-        ioRW(rw),
-        ioEN(en),
-        ioDB(db0, db1, db2, db3, db4, db5, db6, db7),
-        ioCS1(cs1),
-        ioCS2(cs2),
-        ioRES(res) {
-    bufferClear();
-    setDirectionToWrite();
-}
-
-SG12864A::~SG12864A() {
-}
-
-void SG12864A::bufferPush(void) {
-    for (uint8_t i = 0; i < PAGES; i++) {
-        // CS1
-        setPageAddress(SG12864A::CS1, i);
-        setColumnAddress(SG12864A::CS1, 0);
-        for (uint8_t j = 0; j < COLUMNS; j++) {
-            writeData(CS1, buffer[0 + ((COLUMNS * 2) * i) + j]);
-        }
-        // CS2
-        setPageAddress(SG12864A::CS2, i);
-        setColumnAddress(SG12864A::CS2, 0);
-        for (uint8_t j = 0; j < COLUMNS; j++) {
-            writeData(CS2, buffer[COLUMNS + ((COLUMNS * 2) * i) + j]);
-        }
-    }
-}
-
-void SG12864A::bufferPull(void) {
-}
-
-void SG12864A::bufferClear(bool reverse) {
-    for (int i = 0; i < sizeof(buffer); i++) {
-        if (reverse) {
-            buffer[i] = 0xFF;
-        } else {
-            buffer[i] = 0x00;
-        }
-    }
-}
-
-void SG12864A::bufferDrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, bool reverse) {
-    /*
-     * Bresenham's line algorithm
-     */
-    bool steep = abs(y2 - y1) > abs(x2 - x1);
-    if (steep) {
-        swap(x1, y1);
-        swap(x2, y2);
-    }
-    if (x1 > x2) {
-        swap(x1, x2);
-        swap(y1, y2);
-    }
-    int deltax = x2 - x1;
-    int deltay = abs(y2 - y1);
-    int error = deltax / 2;
-    int ystep;
-    int y = y1;
-    if (y1 < y2) {
-        ystep = 1;
-    } else {
-        ystep = -1;
-    }
-    for (int x = x1; x <= x2; x++) {
-        if (steep) {
-            if (reverse) {
-                unsetPixel(y, x);
-            } else {
-                setPixel(y, x);
-            }
-        } else {
-            if (reverse) {
-                unsetPixel(x, y);
-            } else {
-                setPixel(x, y);
-            }
-        }
-        error = error - deltay;
-        if (error < 0) {
-            y = y + ystep;
-            error = error + deltax;
-        }
-    }
-}
-
-void SG12864A::bufferDrawBox(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, bool reverse) {
-    for (int x = x1; x <= x2; x++) {
-        if (reverse) {
-            unsetPixel(x, y1);
-            unsetPixel(x, y2);
-        } else {
-            setPixel(x, y1);
-            setPixel(x, y2);
-        }
-    }
-    for (int y = y1; y <= y2; y++) {
-        if (reverse) {
-            unsetPixel(x1, y);
-            unsetPixel(x2, y);
-        } else {
-            setPixel(x1, y);
-            setPixel(x2, y);
-        }
-    }
-}
-
-void SG12864A::bufferFillBox(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, bool reverse) {
-    for (int x = x1; x <= x2; x++) {
-        for (int y = y1; y <= y2; y++) {
-            if (reverse) {
-                unsetPixel(x, y);
-            } else {
-                setPixel(x, y);
-            }
-        }
-    }
-}
-
-void SG12864A::bufferDrawString(uint8_t x, uint8_t y, char * str, bool reverse) {
-    char *p = str;
-    int cnt = 0;
-    while (*p) {
-        bufferDrawChar(x + (FONT_X * cnt), y, *p, reverse);
-        p++;
-        cnt++;
-    }
-}
-
-void SG12864A::bufferDrawChar(uint8_t x, uint8_t y, char c, bool reverse) {
-    if ((FONT_MIN_CODE <= c) &&(c <= FONT_MAX_CODE)) {
-        int aofs = (c - FONT_MIN_CODE) * FONT_X;
-        for (int i = 0; i < FONT_X; i++) {
-            uint8_t pat = font5x7_data[aofs + i];
-            for (int j = 0; j < FONT_Y; j++) {
-                if (pat & (1 << j)) {
-                    if (reverse) {
-                        unsetPixel(x + i, y + j);
-                    } else {
-                        setPixel(x + i, y + j);
-                    }
-                } else {
-                    if (reverse) {
-                        setPixel(x + i, y + j);
-                    } else {
-                        unsetPixel(x + i, y + j);
-                    }
-                }
-            }
-        }
-    } else {
-        for (int i = 0; i < FONT_X; i++) {
-            uint8_t pat = (i % 2) ? 0x55 : 0xAA;
-            for (int j = 0; j < FONT_Y; j++) {
-                if (pat & (1 << j)) {
-                    if (reverse) {
-                        unsetPixel(x + i, y + j);
-                    } else {
-                        setPixel(x + i, y + j);
-                    }
-                } else {
-                    if (reverse) {
-                        setPixel(x + i, y + j);
-                    } else {
-                        unsetPixel(x + i, y + j);
-                    }
-                }
-            }
-        }
-    }
-}
-
-void SG12864A::bufferDrawCheckbox(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, bool state, bool reverse) {
-    bufferDrawBox(x1, y1, x2, y2, reverse);
-    if (state) {
-        bufferDrawLine(x1, y1, x2, y2, reverse);
-        bufferDrawLine(x1, y2, x2, y1, reverse);
-    }
-}
-
-void SG12864A::bufferDrawProgressbar(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, int min, int max, int value, bool horizontal, bool reverse) {
-    bufferDrawBox(x1, y1, x2, y2, reverse);
-    if ((value < min) || (max < value)) {
-        return;
-    }
-    int tmp_max = max - min;
-    int tmp_val = value - min;
-    if (horizontal) {
-        int pix = ((y2 - y1) * tmp_val) / tmp_max;
-        bufferFillBox(x1 + 1, y1 + 1, x1 - 1, y2 + pix - 1, reverse);
-    } else {
-        int pix = ((x2 - x1) * tmp_val) / tmp_max;
-        bufferFillBox(x1 + 1, y1 + 1, x1 + pix - 1, y2 - 1, reverse);
-    }
-}
-
-/**
- * High Level Interface.
- *
- * Reset display module.
- */
-void SG12864A::reset(void) {
-    reset(true);
-    wait_ms(200);
-    reset(false);
-    wait_ms(200);
-
-    setDisplayOnOff(SG12864A::CS1, true);
-    setDisplayOnOff(SG12864A::CS2, true);
-    setDisplayStartLine(SG12864A::CS1, 0);
-    setDisplayStartLine(SG12864A::CS2, 0);
-    setPageAddress(SG12864A::CS1, 0);
-    setPageAddress(SG12864A::CS2, 0);
-    setColumnAddress(SG12864A::CS1, 0);
-    setColumnAddress(SG12864A::CS2, 0);
-}
-
-/**
- * High Level Interface.
- *
- * Clear display module.
- */
-void SG12864A::clear(void) {
-    for (uint8_t page = 0; page < PAGES; page++) {
-        for (uint8_t column = 0; column < COLUMNS; column++) {
-            // CS1
-            setPageAddress(SG12864A::CS1, page);
-            setColumnAddress(SG12864A::CS1, column);
-            writeData(CS1, 0x00);
-            // CS2
-            setPageAddress(SG12864A::CS2, page);
-            setColumnAddress(SG12864A::CS2, column);
-            writeData(CS2, 0x00);
-        }
-    }
-    // CS1
-    setPageAddress(SG12864A::CS1, 0);
-    setColumnAddress(SG12864A::CS1, 0);
-    writeData(CS1, 0x00);
-    // CS2
-    setPageAddress(SG12864A::CS2, 0);
-    setColumnAddress(SG12864A::CS2, 0);
-    writeData(CS2, 0x00);
-}
-
-/**
- * Middle Level Interface.
- *
- * Set display on/off.
- *
- * @param t Target (CS1, CS2).
- * @param on ON/OFF (true, false).
- */
-void SG12864A::setDisplayOnOff(Target t, bool on) {
-    setDirectionToWrite();
-    uint8_t c = 0x3e | (on ? 0x01 : 0x00);
-    write(t, SG12864A::Instruction, c);
-    wait_us(1);
-}
-
-/**
- * Middle Level Interface.
- *
- * Set display start line.
- *
- * @param t Target (CS1, CS2).
- * @param addr Display start line (0-63).
- */
-void SG12864A::setDisplayStartLine(Target t, uint8_t addr) {
-    setDirectionToWrite();
-    uint8_t c = 0xc0 | (addr & 0x3f);
-    write(t, SG12864A::Instruction, c);
-    wait_us(1);
-}
-
-/**
- * Middle Level Interface.
- *
- * Set page address.
- *
- * @param t Target (CS1, CS2).
- * @param addr Page address(0-7).
- */
-void SG12864A::setPageAddress(Target t, uint8_t addr) {
-    setDirectionToWrite();
-    uint8_t c = 0xb8 | (addr & 0x07);
-    write(t, SG12864A::Instruction, c);
-    wait_us(1);
-}
-
-/**
- * Middle Level Interface.
- *
- * Set column address.
- *
- * @param t Target. (CS1, CS2)
- * @param addr Column address (0-63).
- */
-void SG12864A::setColumnAddress(Target t, uint8_t addr) {
-    setDirectionToWrite();
-    uint8_t c = 0x40 | (addr & 0x3f);
-    write(t, SG12864A::Instruction, c);
-    wait_us(1);
-}
-
-/**
- * Middle Level Interface.
- */
-void SG12864A::readStatus(Target t, uint8_t *c) {
-    setDirectionToRead();
-    read(t, SG12864A::Instruction, c);
-    wait_us(1);
-}
-
-/**
- * Middle Level Interface.
- */
-void SG12864A::writeData(Target t, uint8_t c) {
-    setDirectionToWrite();
-    write(t, SG12864A::Data, c);
-    wait_us(1);
-}
-
-/**
- * Middle Level Interface.
- */
-void SG12864A::readData(Target t, uint8_t *c) {
-    setDirectionToRead();
-    read(t, SG12864A::Data, c);
-    wait_us(1);
-}
-
-/**
- * Low Level Interface.
- */
-void SG12864A::setDirectionToRead() {
-    ioDB.input();
-    ioRW = 1;
-}
-
-/**
- * Low Level Interface.
- */
-void SG12864A::setDirectionToWrite() {
-    ioDB.output();
-    ioRW = 0;
-}
-
-/**
- * Low Level Interface.
- */
-void SG12864A::write(Target t, Mode m, uint8_t c) {
-    switch (t) {
-        case CS1:
-            ioCS1 = 1;
-            ioCS2 = 0;
-            break;
-        case CS2:
-            ioCS1 = 0;
-            ioCS2 = 1;
-            break;
-    }
-    switch (m) {
-        case Data:
-            ioDI = 1;
-            break;
-        case Instruction:
-            ioDI = 0;
-            break;
-    }
-    ioDB = c;
-    wait_us(1);
-    ioEN = 1;
-    wait_us(1);
-    ioEN = 0;
-    wait_us(5);
-}
-
-/**
- * Low Level Interface.
- */
-void SG12864A::read(Target t, Mode m, uint8_t *c) {
-    // TODO
-}
-
-/**
- * Low Level Interface.
- */
-void SG12864A::reset(bool b) {
-    if (b) {
-        ioRES = 0;
-    } else {
-        ioRES = 1;
-    }
-}
+/**
+ * SG12864A Graphics LCD module driver class (Version 0.0.1)
+ *
+ * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems)
+ * http://shinta.main.jp/
+ *
+ * See also ...
+ * http://mbed.org/users/shintamainjp/notebook/sg12864asunlike-display-graphics-lcd-driver/
+ */
+
+#include "SG12864A.h"
+
+#define setPixel(x,y) buffer[((COLUMNS * 2)* ((y) / 8)) + (x)] |= (1 << ((y) % 8))
+#define unsetPixel(x,y) buffer[((COLUMNS * 2)* ((y) / 8)) + (x)] &= ~(1 << ((y) % 8))
+#define swap(a,b) {int c=a;a=b;b=c;}
+
+const uint8_t SG12864A::font5x7_data[] = {
+    0x00, 0x00, 0x00, 0x00, 0x00, // (white space)
+    0x00, 0x00, 0x5F, 0x00, 0x00, // !
+    0x00, 0x07, 0x00, 0x07, 0x00, // "
+    0x14, 0x7F, 0x14, 0x7F, 0x14, // #
+    0x24, 0x2A, 0x7F, 0x2A, 0x12, // $
+    0x23, 0x13, 0x08, 0x64, 0x62, // %
+    0x36, 0x49, 0x55, 0x22, 0x50, // &
+    0x00, 0x05, 0x03, 0x00, 0x00, // '
+    0x00, 0x1C, 0x22, 0x41, 0x00, // (
+    0x00, 0x41, 0x22, 0x1C, 0x00, // )
+    0x08, 0x2A, 0x1C, 0x2A, 0x08, // *
+    0x08, 0x08, 0x3E, 0x08, 0x08, // +
+    0x00, 0x50, 0x30, 0x00, 0x00, // ,
+    0x08, 0x08, 0x08, 0x08, 0x08, // -
+    0x00, 0x60, 0x60, 0x00, 0x00, // .
+    0x20, 0x10, 0x08, 0x04, 0x02, // /
+    0x3E, 0x51, 0x49, 0x45, 0x3E, // 0
+    0x00, 0x42, 0x7F, 0x40, 0x00, // 1
+    0x42, 0x61, 0x51, 0x49, 0x46, // 2
+    0x21, 0x41, 0x45, 0x4B, 0x31, // 3
+    0x18, 0x14, 0x12, 0x7F, 0x10, // 4
+    0x27, 0x45, 0x45, 0x45, 0x39, // 5
+    0x3C, 0x4A, 0x49, 0x49, 0x30, // 6
+    0x01, 0x71, 0x09, 0x05, 0x03, // 7
+    0x36, 0x49, 0x49, 0x49, 0x36, // 8
+    0x06, 0x49, 0x49, 0x29, 0x1E, // 9
+    0x00, 0x36, 0x36, 0x00, 0x00, // :
+    0x00, 0x56, 0x36, 0x00, 0x00, // ;
+    0x00, 0x08, 0x14, 0x22, 0x41, // <
+    0x14, 0x14, 0x14, 0x14, 0x14, // =
+    0x41, 0x22, 0x14, 0x08, 0x00, // >
+    0x02, 0x01, 0x51, 0x09, 0x06, // ?
+    0x32, 0x49, 0x79, 0x41, 0x3E, // @
+    0x7E, 0x11, 0x11, 0x11, 0x7E, // A
+    0x7F, 0x49, 0x49, 0x49, 0x36, // B
+    0x3E, 0x41, 0x41, 0x41, 0x22, // C
+    0x7F, 0x41, 0x41, 0x22, 0x1C, // D
+    0x7F, 0x49, 0x49, 0x49, 0x41, // E
+    0x7F, 0x09, 0x09, 0x01, 0x01, // F
+    0x3E, 0x41, 0x41, 0x51, 0x32, // G
+    0x7F, 0x08, 0x08, 0x08, 0x7F, // H
+    0x00, 0x41, 0x7F, 0x41, 0x00, // I
+    0x20, 0x40, 0x41, 0x3F, 0x01, // J
+    0x7F, 0x08, 0x14, 0x22, 0x41, // K
+    0x7F, 0x40, 0x40, 0x40, 0x40, // L
+    0x7F, 0x02, 0x04, 0x02, 0x7F, // M
+    0x7F, 0x04, 0x08, 0x10, 0x7F, // N
+    0x3E, 0x41, 0x41, 0x41, 0x3E, // O
+    0x7F, 0x09, 0x09, 0x09, 0x06, // P
+    0x3E, 0x41, 0x51, 0x21, 0x5E, // Q
+    0x7F, 0x09, 0x19, 0x29, 0x46, // R
+    0x46, 0x49, 0x49, 0x49, 0x31, // S
+    0x01, 0x01, 0x7F, 0x01, 0x01, // T
+    0x3F, 0x40, 0x40, 0x40, 0x3F, // U
+    0x1F, 0x20, 0x40, 0x20, 0x1F, // V
+    0x7F, 0x20, 0x18, 0x20, 0x7F, // W
+    0x63, 0x14, 0x08, 0x14, 0x63, // X
+    0x03, 0x04, 0x78, 0x04, 0x03, // Y
+    0x61, 0x51, 0x49, 0x45, 0x43, // Z
+    0x00, 0x00, 0x7F, 0x41, 0x41, // [
+    0x02, 0x04, 0x08, 0x10, 0x20, // /
+    0x41, 0x41, 0x7F, 0x00, 0x00, // ]
+    0x04, 0x02, 0x01, 0x02, 0x04, // ^
+    0x40, 0x40, 0x40, 0x40, 0x40, // _
+    0x00, 0x01, 0x02, 0x04, 0x00, // `
+    0x20, 0x54, 0x54, 0x54, 0x78, // a
+    0x7F, 0x48, 0x44, 0x44, 0x38, // b
+    0x38, 0x44, 0x44, 0x44, 0x20, // c
+    0x38, 0x44, 0x44, 0x48, 0x7F, // d
+    0x38, 0x54, 0x54, 0x54, 0x18, // e
+    0x08, 0x7E, 0x09, 0x01, 0x02, // f
+    0x08, 0x14, 0x54, 0x54, 0x3C, // g
+    0x7F, 0x08, 0x04, 0x04, 0x78, // h
+    0x00, 0x44, 0x7D, 0x40, 0x00, // i
+    0x20, 0x40, 0x44, 0x3D, 0x00, // j
+    0x00, 0x7F, 0x10, 0x28, 0x44, // k
+    0x00, 0x41, 0x7F, 0x40, 0x00, // l
+    0x7C, 0x04, 0x18, 0x04, 0x78, // m
+    0x7C, 0x08, 0x04, 0x04, 0x78, // n
+    0x38, 0x44, 0x44, 0x44, 0x38, // o
+    0x7C, 0x14, 0x14, 0x14, 0x08, // p
+    0x08, 0x14, 0x14, 0x18, 0x7C, // q
+    0x7C, 0x08, 0x04, 0x04, 0x08, // r
+    0x48, 0x54, 0x54, 0x54, 0x20, // s
+    0x04, 0x3F, 0x44, 0x40, 0x20, // t
+    0x3C, 0x40, 0x40, 0x20, 0x7C, // u
+    0x1C, 0x20, 0x40, 0x20, 0x1C, // v
+    0x3C, 0x40, 0x30, 0x40, 0x3C, // w
+    0x44, 0x28, 0x10, 0x28, 0x44, // x
+    0x0C, 0x50, 0x50, 0x50, 0x3C, // y
+    0x44, 0x64, 0x54, 0x4C, 0x44, // z
+    0x00, 0x08, 0x36, 0x41, 0x00, // {
+    0x00, 0x00, 0x7F, 0x00, 0x00, // |
+    0x00, 0x41, 0x36, 0x08, 0x00, // }
+    0x08, 0x08, 0x2A, 0x1C, 0x08, // ->
+    0x08, 0x1C, 0x2A, 0x08, 0x08  // <-
+};
+
+SG12864A::SG12864A(PinName di,
+                   PinName rw,
+                   PinName en,
+                   PinName db0,
+                   PinName db1,
+                   PinName db2,
+                   PinName db3,
+                   PinName db4,
+                   PinName db5,
+                   PinName db6,
+                   PinName db7,
+                   PinName cs1,
+                   PinName cs2,
+                   PinName res)
+        :
+        ioDI(di),
+        ioRW(rw),
+        ioEN(en),
+        ioDB(db0, db1, db2, db3, db4, db5, db6, db7),
+        ioCS1(cs1),
+        ioCS2(cs2),
+        ioRES(res) {
+    bufferClear();
+    setDirectionToWrite();
+}
+
+SG12864A::~SG12864A() {
+}
+
+void SG12864A::bufferPush(void) {
+    for (uint8_t i = 0; i < PAGES; i++) {
+        // CS1
+        setPageAddress(SG12864A::CS1, i);
+        setColumnAddress(SG12864A::CS1, 0);
+        for (uint8_t j = 0; j < COLUMNS; j++) {
+            writeData(CS1, buffer[0 + ((COLUMNS * 2) * i) + j]);
+        }
+        // CS2
+        setPageAddress(SG12864A::CS2, i);
+        setColumnAddress(SG12864A::CS2, 0);
+        for (uint8_t j = 0; j < COLUMNS; j++) {
+            writeData(CS2, buffer[COLUMNS + ((COLUMNS * 2) * i) + j]);
+        }
+    }
+}
+
+void SG12864A::bufferPull(void) {
+}
+
+void SG12864A::bufferClear(bool reverse) {
+    for (int i = 0; i < sizeof(buffer); i++) {
+        if (reverse) {
+            buffer[i] = 0xFF;
+        } else {
+            buffer[i] = 0x00;
+        }
+    }
+}
+
+void SG12864A::bufferDrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, bool reverse) {
+    /*
+     * Bresenham's line algorithm
+     */
+    bool steep = abs(y2 - y1) > abs(x2 - x1);
+    if (steep) {
+        swap(x1, y1);
+        swap(x2, y2);
+    }
+    if (x1 > x2) {
+        swap(x1, x2);
+        swap(y1, y2);
+    }
+    int deltax = x2 - x1;
+    int deltay = abs(y2 - y1);
+    int error = deltax / 2;
+    int ystep;
+    int y = y1;
+    if (y1 < y2) {
+        ystep = 1;
+    } else {
+        ystep = -1;
+    }
+    for (int x = x1; x <= x2; x++) {
+        if (steep) {
+            if (reverse) {
+                unsetPixel(y, x);
+            } else {
+                setPixel(y, x);
+            }
+        } else {
+            if (reverse) {
+                unsetPixel(x, y);
+            } else {
+                setPixel(x, y);
+            }
+        }
+        error = error - deltay;
+        if (error < 0) {
+            y = y + ystep;
+            error = error + deltax;
+        }
+    }
+}
+
+void SG12864A::bufferDrawBox(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, bool reverse) {
+    for (int x = x1; x <= x2; x++) {
+        if (reverse) {
+            unsetPixel(x, y1);
+            unsetPixel(x, y2);
+        } else {
+            setPixel(x, y1);
+            setPixel(x, y2);
+        }
+    }
+    for (int y = y1; y <= y2; y++) {
+        if (reverse) {
+            unsetPixel(x1, y);
+            unsetPixel(x2, y);
+        } else {
+            setPixel(x1, y);
+            setPixel(x2, y);
+        }
+    }
+}
+
+void SG12864A::bufferFillBox(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, bool reverse) {
+    for (int x = x1; x <= x2; x++) {
+        for (int y = y1; y <= y2; y++) {
+            if (reverse) {
+                unsetPixel(x, y);
+            } else {
+                setPixel(x, y);
+            }
+        }
+    }
+}
+
+void SG12864A::bufferDrawString(uint8_t x, uint8_t y, char * str, bool reverse) {
+    char *p = str;
+    int cnt = 0;
+    while (*p) {
+        bufferDrawChar(x + (FONT_X * cnt), y, *p, reverse);
+        p++;
+        cnt++;
+    }
+}
+
+void SG12864A::bufferDrawChar(uint8_t x, uint8_t y, char c, bool reverse) {
+    if ((FONT_MIN_CODE <= c) &&(c <= FONT_MAX_CODE)) {
+        int aofs = (c - FONT_MIN_CODE) * FONT_X;
+        for (int i = 0; i < FONT_X; i++) {
+            uint8_t pat = font5x7_data[aofs + i];
+            for (int j = 0; j < FONT_Y; j++) {
+                if (pat & (1 << j)) {
+                    if (reverse) {
+                        unsetPixel(x + i, y + j);
+                    } else {
+                        setPixel(x + i, y + j);
+                    }
+                } else {
+                    if (reverse) {
+                        setPixel(x + i, y + j);
+                    } else {
+                        unsetPixel(x + i, y + j);
+                    }
+                }
+            }
+        }
+    } else {
+        for (int i = 0; i < FONT_X; i++) {
+            uint8_t pat = (i % 2) ? 0x55 : 0xAA;
+            for (int j = 0; j < FONT_Y; j++) {
+                if (pat & (1 << j)) {
+                    if (reverse) {
+                        unsetPixel(x + i, y + j);
+                    } else {
+                        setPixel(x + i, y + j);
+                    }
+                } else {
+                    if (reverse) {
+                        setPixel(x + i, y + j);
+                    } else {
+                        unsetPixel(x + i, y + j);
+                    }
+                }
+            }
+        }
+    }
+}
+
+void SG12864A::bufferDrawCheckbox(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, bool state, bool reverse) {
+    bufferDrawBox(x1, y1, x2, y2, reverse);
+    if (state) {
+        bufferDrawLine(x1, y1, x2, y2, reverse);
+        bufferDrawLine(x1, y2, x2, y1, reverse);
+    }
+}
+
+void SG12864A::bufferDrawProgressbar(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, int min, int max, int value, bool reverse) {
+    bufferDrawBox(x1, y1, x2, y2, reverse);
+    if ((value < min) || (max < value)) {
+        return;
+    }
+    int tmp_max = max - min;
+    int tmp_val = value - min;
+    int pix = ((x2 - x1) * tmp_val) / tmp_max;
+    bufferFillBox(x1 + 1, y1 + 1, x1 + pix - 1, y2 - 1, reverse);
+}
+
+/**
+ * High Level Interface.
+ *
+ * Reset display module.
+ */
+void SG12864A::reset(void) {
+    reset(true);
+    wait_ms(200);
+    reset(false);
+    wait_ms(200);
+
+    setDisplayOnOff(SG12864A::CS1, true);
+    setDisplayOnOff(SG12864A::CS2, true);
+    setDisplayStartLine(SG12864A::CS1, 0);
+    setDisplayStartLine(SG12864A::CS2, 0);
+    setPageAddress(SG12864A::CS1, 0);
+    setPageAddress(SG12864A::CS2, 0);
+    setColumnAddress(SG12864A::CS1, 0);
+    setColumnAddress(SG12864A::CS2, 0);
+}
+
+/**
+ * High Level Interface.
+ *
+ * Clear display module.
+ */
+void SG12864A::clear(void) {
+    for (uint8_t page = 0; page < PAGES; page++) {
+        for (uint8_t column = 0; column < COLUMNS; column++) {
+            // CS1
+            setPageAddress(SG12864A::CS1, page);
+            setColumnAddress(SG12864A::CS1, column);
+            writeData(CS1, 0x00);
+            // CS2
+            setPageAddress(SG12864A::CS2, page);
+            setColumnAddress(SG12864A::CS2, column);
+            writeData(CS2, 0x00);
+        }
+    }
+    // CS1
+    setPageAddress(SG12864A::CS1, 0);
+    setColumnAddress(SG12864A::CS1, 0);
+    writeData(CS1, 0x00);
+    // CS2
+    setPageAddress(SG12864A::CS2, 0);
+    setColumnAddress(SG12864A::CS2, 0);
+    writeData(CS2, 0x00);
+}
+
+/**
+ * Middle Level Interface.
+ *
+ * Set display on/off.
+ *
+ * @param t Target (CS1, CS2).
+ * @param on ON/OFF (true, false).
+ */
+void SG12864A::setDisplayOnOff(Target t, bool on) {
+    setDirectionToWrite();
+    uint8_t c = 0x3e | (on ? 0x01 : 0x00);
+    write(t, SG12864A::Instruction, c);
+    wait_us(1);
+}
+
+/**
+ * Middle Level Interface.
+ *
+ * Set display start line.
+ *
+ * @param t Target (CS1, CS2).
+ * @param addr Display start line (0-63).
+ */
+void SG12864A::setDisplayStartLine(Target t, uint8_t addr) {
+    setDirectionToWrite();
+    uint8_t c = 0xc0 | (addr & 0x3f);
+    write(t, SG12864A::Instruction, c);
+    wait_us(1);
+}
+
+/**
+ * Middle Level Interface.
+ *
+ * Set page address.
+ *
+ * @param t Target (CS1, CS2).
+ * @param addr Page address(0-7).
+ */
+void SG12864A::setPageAddress(Target t, uint8_t addr) {
+    setDirectionToWrite();
+    uint8_t c = 0xb8 | (addr & 0x07);
+    write(t, SG12864A::Instruction, c);
+    wait_us(1);
+}
+
+/**
+ * Middle Level Interface.
+ *
+ * Set column address.
+ *
+ * @param t Target. (CS1, CS2)
+ * @param addr Column address (0-63).
+ */
+void SG12864A::setColumnAddress(Target t, uint8_t addr) {
+    setDirectionToWrite();
+    uint8_t c = 0x40 | (addr & 0x3f);
+    write(t, SG12864A::Instruction, c);
+    wait_us(1);
+}
+
+/**
+ * Middle Level Interface.
+ */
+void SG12864A::readStatus(Target t, uint8_t *c) {
+    setDirectionToRead();
+    read(t, SG12864A::Instruction, c);
+    wait_us(1);
+}
+
+/**
+ * Middle Level Interface.
+ */
+void SG12864A::writeData(Target t, uint8_t c) {
+    setDirectionToWrite();
+    write(t, SG12864A::Data, c);
+    wait_us(1);
+}
+
+/**
+ * Middle Level Interface.
+ */
+void SG12864A::readData(Target t, uint8_t *c) {
+    setDirectionToRead();
+    read(t, SG12864A::Data, c);
+    wait_us(1);
+}
+
+/**
+ * Low Level Interface.
+ */
+void SG12864A::setDirectionToRead() {
+    ioDB.input();
+    ioRW = 1;
+}
+
+/**
+ * Low Level Interface.
+ */
+void SG12864A::setDirectionToWrite() {
+    ioDB.output();
+    ioRW = 0;
+}
+
+/**
+ * Low Level Interface.
+ */
+void SG12864A::write(Target t, Mode m, uint8_t c) {
+    switch (t) {
+        case CS1:
+            ioCS1 = 1;
+            ioCS2 = 0;
+            break;
+        case CS2:
+            ioCS1 = 0;
+            ioCS2 = 1;
+            break;
+    }
+    switch (m) {
+        case Data:
+            ioDI = 1;
+            break;
+        case Instruction:
+            ioDI = 0;
+            break;
+    }
+    ioDB = c;
+    wait_us(1);
+    ioEN = 1;
+    wait_us(1);
+    ioEN = 0;
+    wait_us(5);
+}
+
+/**
+ * Low Level Interface.
+ */
+void SG12864A::read(Target t, Mode m, uint8_t *c) {
+    // TODO
+}
+
+/**
+ * Low Level Interface.
+ */
+void SG12864A::reset(bool b) {
+    if (b) {
+        ioRES = 0;
+    } else {
+        ioRES = 1;
+    }
+}