aitendo C128X64SPI-12P-M with FRDM KL25Z
aitendo の FSTN液晶モジュール(128x64/SPI)[C128X64SPI-12P-M] を KL25Z につないでみました。今のところ、ドット、ライン操作までしか用意できていません。コントローラ仕様によるとデバイスからデータを取得することができるのですが、シリアル(SPI)ではできないことになっているため、フレームバッファは自前で持っています。テスト用にドラゴン曲線を表示させてみました。
ところで aitendo の商品説明ページ中の FPCケーブル取り付け例の写真は誤っていました(修正された模様)。また、キャリーボードでの LCD とバックライトの GND と電源は直結されているようです。ついでにサンプルのコードでのフレームバッファの使い方にも誤りがありますからドット単位で操作する場合には注意が必要です。
2014.03.12
q61.org さんの Chibimo 表示器として使えるようにしてみました。ドラゴン曲線を描いた後、ホストからの Chibimo データを処理します。KL05 とトラ技 ARM ライタ基板でも動作を確認していますが、Chibimo として使うには USB シリアルの使える KL* が良いでしょう。
Diff: c128x64spi.cpp
- Revision:
- 0:b06afbefd350
- Child:
- 1:84b2d36d57f0
diff -r 000000000000 -r b06afbefd350 c128x64spi.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/c128x64spi.cpp Sun Jun 16 13:50:27 2013 +0000 @@ -0,0 +1,235 @@ +#include "mbed.h" +#include "c128x64spi.h" + +#define PAGE_SEL 0xB0 +#define COL_SEL 0x10 + +const char init_cmd[] = { + 0xE2, // S/W RESET + 0xA3, // LCD bias + // 0xAF, // Display ON + 0xA0, // segment direction + 0xC8, // Common direction + 0x22, // Regulation register select + 0x81, // EV select + 0x2F, // Select EV value + 0x2F, // Power control + // + 0x40, // initialy display line 40 + 0xB0, // set page address + 0x10, // set column addr MSB + 0x00, // set column addr LSB + // 0xAF, // display ON + 0xA4, // A5 .normal display, all pixels OFF + 0xA6, // A7 .normal display (inverse pixel) + 0xAF, // display ON +}; + +c128x64spi::c128x64spi(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName rs, PinName reset) + : _spi(mosi, miso, sclk), _cs(cs), _rs(rs), _reset(reset) { + int i, j; + + for (i = 0; i < 8; i++) + for (j = 0; j < 128; j++) + gfx_buf[i][j] = 0; + + // _spi.format(8, 3); // 8 bit spi mode 3 + _spi.frequency(8000000); // 8MHz SPI clock .. + + _cs = 0; + _reset = 0; // reset + wait_ms(500); + _reset = 1; + + for (i = 0; i < sizeof(init_cmd); i++) { + wr_cmd(init_cmd[i]); + } +} + +void c128x64spi::hline(int x0, int x1, int y, int color) { + for (int x = x0; x < x1; x++) + pixel(x, y, color); +} + +void c128x64spi::vline(int x, int y0, int y1, int color) { + for (int y = y0; y < y1; y++) { + pixel(x, y, color); + } +} + +void c128x64spi::line(int x0, int y0, int x1, int y1, int color) { +#if 1 + int dx = 0, dy = 0; + int dx_sym = 0, dy_sym = 0; + int dx_x2 = 0, dy_x2 = 0; + int di = 0; + + dx = x1-x0; + dy = y1-y0; + + if (dx == 0) { /* vertical line */ + if (y1 > y0) vline(x0,y0,y1,color); + else vline(x0,y1,y0,color); + return; + } + + if (dx > 0) { + dx_sym = 1; + } else { + dx_sym = -1; + } + if (dy == 0) { /* horizontal line */ + if (x1 > x0) hline(x0,x1,y0,color); + else hline(x1,x0,y0,color); + return; + } + + if (dy > 0) { + dy_sym = 1; + } else { + dy_sym = -1; + } + + dx = dx_sym*dx; + dy = dy_sym*dy; + + dx_x2 = dx*2; + dy_x2 = dy*2; + + if (dx >= dy) { + di = dy_x2 - dx; + while (x0 != x1) { + + pixel(x0, y0, color); + x0 += dx_sym; + if (di<0) { + di += dy_x2; + } else { + di += dy_x2 - dx_x2; + y0 += dy_sym; + } + } + pixel(x0, y0, color); + } else { + di = dx_x2 - dy; + while (y0 != y1) { + pixel(x0, y0, color); + y0 += dy_sym; + if (di < 0) { + di += dx_x2; + } else { + di += dx_x2 - dy_x2; + x0 += dx_sym; + } + } + pixel(x0, y0, color); + } +#else + int dx, dy; + int sx, sy; + int chg; + int e; + int i; + int tmp; + + if (x0 > x1) { + sx = -1; dx = x0 - x1; + } else { + sx = 1; dx = x1 - x0; + } + if (y0 > y1) { + sy = -1; dy = y0 - y1; + } else { + sy = 1; dy = y1 - y0; + } + + if (dy > dx) { + tmp = dx; dx = dy; dy = tmp; + chg = 1; + } else { + chg = 0; + } + + e = (dy << 1) - dx; + for (i = 0; i <= dx; i++) { + pixel(x0, y0, color); + if (e >= 0) { + if (chg) + x0 += sx; + else + y0 += sy; + e -= (dx << 1); + } + if (chg) + y0 += sy; + else + x0 += sx; + e += (dy << 1); + } +#endif +} + +void c128x64spi::clr(int sw) { + int x, y; + + if (sw) sw = 0xff; + + for (y = 0; y < 8; y++) { + // int page = y / 8; + // wr_cmd(PAGE_SEL | y); + for (x = 0; x < 128; x++) { + wr_cmd(PAGE_SEL | y); + int col = ((x & 0xF0) >> 4) | 0x10; + wr_cmd(COL_SEL | col); + wr_cmd(x & 0xf); + + gfx_buf[y][x] = sw; + wr_dat(sw); + } + } +} + +void c128x64spi::pixel(int x, int y, int sw) { + if ((x < 0) || (x >= 128)) return; + if ((y < 0) || (y >= 64)) return; + + int page, col; + int row_in_page; + + page = y / 8; + + /* Selecting Page */ + wr_cmd(PAGE_SEL | page); + + /* Selecting Column */ + col = ((x & 0xF0) >> 4) | 0x10; + wr_cmd(COL_SEL|col); + wr_cmd(x & 0xf); + + /* Pixel location */ + row_in_page = y % 8; + + if (sw) + gfx_buf[page][x] |= (1 << row_in_page); + else + gfx_buf[page][x] &= ~(1 << row_in_page); + + wr_dat(gfx_buf[page][x]); +} + +void c128x64spi::wr_cmd(int cmd) { + _rs = 0; // rs low, cs low for transmitting command + _cs = 0; + _spi.write(cmd); + // wait_ms(5); + _cs = 1; +} + +void c128x64spi::wr_dat(int dat) { + _rs = 1; // rs high, cs low for transmitting data + _cs = 0; + _spi.write(dat); + // wait_ms(5); + _cs = 1; +} +