// // raspTFT2: TFT LCD module (for M032C1289TP (SSD1289) + Touch-panel) // xkozima@myu.ac.jp #include "raspGPIO.h" #include "raspTFT2.h" // 24bit RGB から 16bit RGB への変換 #define TFT_RGB24TO16(r,g,b) ((((r)&0xf8)<<8)|(((g)&0xfc)<<3)|(((b)&0xf8)>>3)) // tft_init: LCD モジュールの初期化 void TFT::init () { // D/C 出力,タッチ+左右クリック 入力 gpio_init(); gpio_configure(TFT_GPIO_DC, GPIO_OUTPUT); // D/C 出力 gpio_configure(TFT_GPIO_PENIRQ, GPIO_INPUT); // タッチ入力 gpio_configure_pull(TFT_GPIO_PENIRQ, GPIO_PULLUP); gpio_configure(TFT_GPIO_LEFT, GPIO_INPUT); // 左クリック gpio_configure_pull(TFT_GPIO_LEFT, GPIO_PULLUP); gpio_configure(TFT_GPIO_RIGHT, GPIO_INPUT); // 右クリック gpio_configure_pull(TFT_GPIO_RIGHT, GPIO_PULLUP); // TFT への SPI0 を初期化 spi0.init("/dev/spidev0.0", 16000000); // LCD への初期化コマンド sendCommandData2(0x00, 0x00, 0x01); // OSCEN=1 (start oscillator) sendCommandData2(0x03, 0xa2, 0xa4); // power control 1 sendCommandData2(0x0c, 0x00, 0x04); // power control 2 sendCommandData2(0x0d, 0x03, 0x08); // power control 3 sendCommandData2(0x0e, 0x30, 0x00); // power control 4 sendCommandData2(0x1e, 0x00, 0xea); // power control 5 sendCommandData2(0x01, 0x2b, 0x3f); // !RL,REV,!CAD,BGR,!SM,TB,MUX=13f sendCommandData2(0x02, 0x06, 0x00); // !FLD,!ENWS,DC,EOR,!WSMD,NW=00 sendCommandData2(0x10, 0x00, 0x00); // !SLP (exit sleep mode) usleep(30000); sendCommandData2(0x11, 0x60, 0x28); // 65k,TypeA,landscape(ID=10,AM=1) sendCommandData2(0x07, 0x00, 0x33); // GON=1, DTE=1, D=11 sendCommandData2(0x0b, 0x00, 0x39); // frame cycle sendCommandData2(0x0f, 0x00, 0x00); // gate scan start usleep(10000); // タッチパネルへの SPI1 を初期化 spi1.init("/dev/spidev0.1", 1000000); touchN = 0; // タッチ連続数(ノイズ除去用) } // tft_send: 画像データ(1フレーム分)の転送 void TFT::sendFrame (unsigned char *frame) { gpio_set(TFT_GPIO_DC); // D/C に「データ」を設定 sendBuffer(frame, 0, 0, TFT_WIDTH, TFT_HEIGHT); } // tft_send: 画像データ(矩形領域)の転送 void TFT::sendBuffer (unsigned char *buffer, int x, int y, int w, int h) { // 描画領域指定 (x, y, w, h) int xx1 = x; int xx2 = x + w - 1; sendCommandData2(0x45, xx1 >> 8, xx1 & 0xff); sendCommandData2(0x46, xx2 >> 8, xx2 & 0xff); int yy1 = 239 - y; int yy2 = 239 - (y + h - 1); sendCommandData2(0x44, yy1, yy2); // 描画開始位置 (0, 0) sendCommandData2(0x4e, 0, yy1); sendCommandData2(0x4f, xx1 >> 8, xx1 & 0xff); // ピクセル描画(自動インクリメント) sendCommand1(0x22); // 描画コマンド送信 // データ転送 gpio_set(TFT_GPIO_DC); // D/C に「データ」を設定 spi0.sendBuffer(buffer, w * h * 2); // ピクセルデータ転送 } // タッチパネルの読み取り int TFT::getTouch(int *x, int *y) { // タッチがあれば座標を読み取る if (gpio_read(TFT_GPIO_PENIRQ) == 0) { unsigned char send[3], rec[3]; // X軸の読み取り(12bit: 0x00:0x7f:0xf8) send[0] = 0x94; send[1] = 0x00; send[2] = 0x00; spi1.sendRecN(send, rec, 3); int xraw = ((rec[1] & 0x7f) << 5) | ((rec[2] & 0xf8) >> 3); // Y軸の読み取り(12bit: 0x00:0x7f:0xf8) send[0] = 0xD4; send[1] = 0x00; send[2] = 0x00; spi1.sendRecN(send, rec, 3); int yraw = ((rec[1] & 0x7f) << 5) | ((rec[2] & 0xf8) >> 3); // ノイズ除去 if (touchN == 0) { // 最初のデータが不安定なので無視 touchN++; return TFT_TOUCH_NONE; } else if (touchN == 1) { // 2回目のデータを採用 touchX = xraw; touchY = yraw; touchN++; } else { // それ以降は平滑化 touchX = TFT_TOUCH_ALPHA * xraw + (1.0 - TFT_TOUCH_ALPHA) * touchX; touchY = TFT_TOUCH_ALPHA * yraw + (1.0 - TFT_TOUCH_ALPHA) * touchY; touchN++; } // 画面座標に変換(いいかげん) int xpos = -0.0918 * touchX + 350.00; int ypos = -0.0678 * touchY + 260.00; if (xpos < 0) xpos = 0; else if (xpos >= TFT_WIDTH) xpos = TFT_WIDTH - 1; if (ypos < 0) ypos = 0; else if (ypos >= TFT_HEIGHT) ypos = TFT_HEIGHT - 1; *x = xpos; // 画面座標 *y = ypos; // を返す // ボタン状態を返す(押されていなければ画面スクロール) return (gpio_read(TFT_GPIO_LEFT) == 0)? ((gpio_read(TFT_GPIO_RIGHT) == 0)? TFT_TOUCH_2: TFT_TOUCH_1 ): ((gpio_read(TFT_GPIO_RIGHT) == 0)? TFT_TOUCH_3: TFT_TOUCH_SCR ); } else { // タッチなし touchN = 0; return TFT_TOUCH_NONE; } } // sendCommand1: 引数なし制御コマンド(com)を送信 void TFT::sendCommand1 (unsigned char cmd) { // D/C=0(コマンド) gpio_clear(TFT_GPIO_DC); usleep(1); // 16bit コマンド送信(実際には下位 8bit のみ有効) spi0.send1(cmd); spi0.send1(0); usleep(1); } // sendCommand2: 2バイトの制御コマンド(upper:lower)を送信 void TFT::sendCommand2 (unsigned char upper, unsigned char lower) { // D/C=0(コマンド) gpio_clear(TFT_GPIO_DC); usleep(1); // 16bit コマンド送信(upper:lower) spi0.send1(lower); spi0.send1(upper); usleep(1); } // sendData2: 2バイトのデータ(upper:lower)を送信 void TFT::sendData2 (unsigned char upper, unsigned char lower) { // D/C=0(コマンド) gpio_set(TFT_GPIO_DC); usleep(1); // 16bit コマンド送信(upper:lower) spi0.send1(lower); spi0.send1(upper); usleep(1); } // tft_comdat: 引数つき制御コマンド(cmd, data1, data2)を送信 void TFT::sendCommandData2 (unsigned char cmd, unsigned char data1, unsigned char data2) { // 16bit コマンド送信(実際には下位 8bit のみ有効) sendCommand2(0, cmd); // 16bit データ送信 sendData2(data1, data2); } // test_init: カラーテストパターン (width x height) を生成 void TFT::setTestPattern (unsigned char *buffer, int width, int height) { unsigned short colors[7]; int x, y; float bandWidth; // 上段の7帯 colors[0] = TFT_RGB24TO16(192, 192, 192); // gray colors[1] = TFT_RGB24TO16(192, 192, 0); // yellow colors[2] = TFT_RGB24TO16( 0, 192, 192); // cyan colors[3] = TFT_RGB24TO16( 0, 192, 0); // green colors[4] = TFT_RGB24TO16(192, 0, 192); // magenta colors[5] = TFT_RGB24TO16(192, 0, 0); // red colors[6] = TFT_RGB24TO16( 0, 0, 192); // blue int limit1 = height * 2 / 3; bandWidth = width / 7.0; for (y = 0; y < limit1; y++) { for (x = 0; x < width; x++) { int index = x / bandWidth; if (index > 6) index = 6; *buffer++ = colors[index] & 0xff; *buffer++ = colors[index] >> 8; } } // 中断の7帯(ここではグレーのグラデーション) colors[0] = TFT_RGB24TO16( 0, 0, 0); colors[1] = TFT_RGB24TO16( 42, 42, 42); colors[2] = TFT_RGB24TO16( 84, 84, 84); colors[3] = TFT_RGB24TO16(126, 126, 126); colors[4] = TFT_RGB24TO16(168, 168, 168); colors[5] = TFT_RGB24TO16(210, 210, 210); colors[6] = TFT_RGB24TO16(252, 252, 252); int limit2 = limit1 + height / 12; for (y = limit1; y < limit2; y++) { for (x = 0; x < width; x++) { int index = x / bandWidth; if (index > 6) index = 6; *buffer++ = colors[index] & 0xff; *buffer++ = colors[index] >> 8; } } // 下段の6帯(ここでは RGB 100%, 25%) colors[0] = TFT_RGB24TO16(255, 0, 0); // red 100% colors[1] = TFT_RGB24TO16( 64, 0, 0); // red 25% colors[2] = TFT_RGB24TO16( 0, 255, 0); // green 100% colors[3] = TFT_RGB24TO16( 0, 64, 0); // green 25% colors[4] = TFT_RGB24TO16( 0, 0, 255); // blue 100% colors[5] = TFT_RGB24TO16( 0, 0, 64); // blue 25% bandWidth = width / 6.0; for (y = limit2; y < height; y++) { for (x = 0; x < width; x++) { int index = x / bandWidth; if (index > 5) index = 5; *buffer++ = colors[index] & 0xff; *buffer++ = colors[index] >> 8; } } } //