SG12864A
Dependents: SG12864A_TestProgram
Diff: SG12864A.cpp
- 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; + } +}