表示器 (ST7735B 1.8" TFT SPI)

2013/05/11


◆ カラー TFT 液晶

目標だったフルカラーグラフィック液晶の制御に挑戦します。

デバイスは aitendo で購入した SPI制御の TFT 液晶モジュール T18003T01 Adafruit のシールドが同じモジュールを使用しているのでライブラリがそのまま使用できます。

本デバイスの動作電源は 3.0 - 3.4 V となっているので、Arduino UNO 等の 5V で制御すると壊れてしまいます。 分圧して 3.3V へレベルシフトするか、FIO や MINI の 3.3V 版を使用します。

キャリーボードとセットで買ったのでキャリーボードのピン配置を記録しておく。 実験ではカッコ内のように配線しています。

1.8 インチ液晶 with キャリーボード
コントローラ ST7735B
解像度 128 x 160 dot (262K color)

  1.NC     → -
  2.GND    → GND
  3.LED-K  → GND
  4.LED-A  → 3.3V
  5.GND    → GND
  6.RESET  → RESET          ( D8)
  7.RS     → Data / Command ( D9)
  8.SDA    → MOSI           (D11)
  9.SCL    → SCLK           (D13)
 10.Vcc    → 3.3V
 11.Vcc    → 3.3V
 12.CS     → Chip Select    (D10)
 13.GND    → GND
 14.NC     → -

◆ SPI 制御用関数

フルカラーのグラフィックを扱うには膨大なデータを送信する必要があり出来ればソフトウェア SPI ではなく、ハードウェア SPI で少しでも処理速度を上げたいところです。 以下は Arduino の SPI.h を使用したデータ/コマンドの転送関数です。

SPI CLOCK を DIV2 や DIV8 で試してみましたが速度はあまり変わりませんでした。

//
// Div 005-01 ハードウェア SPI によるデータ/コマンド転送関数
//

#include <SPI.h>

// 配線状態
#define pin_RST  8  //  6.Reset
#define pin_RS   9  //  7.RS 
#define pin_CS  10  // 12,CS
//        MOSI  11
//        SCLK  13

void setup() {
  pinMode(pin_RST, OUTPUT);
  pinMode(pin_RS,  OUTPUT);
  pinMode(pin_CS,  OUTPUT);

  SPI.begin();                          // SPI start
  SPI.setClockDivider(SPI_CLOCK_DIV4);  // 16 MHz / 4 = 4 MHz
  SPI.setBitOrder(MSBFIRST);            // MSB first
  SPI.setDataMode(SPI_MODE0);           // Mode 0
}

void loop() {
}

// コマンド送信関数
void writeCommand(byte b) {
  digitalWrite(pin_CS, LOW);
  digitalWrite(pin_RS, LOW);
  SPDR = b;
  while (!(SPSR & _BV(SPIF)));
  digitalWrite(pin_CS, HIGH);
}

// データ送信関数
void writeData(byte b) {
  digitalWrite(pin_CS, LOW);
  digitalWrite(pin_RS, HIGH);
  SPDR = b;
  while (!(SPSR & _BV(SPIF)));
  digitalWrite(pin_CS, HIGH);
}

// ハードウェアリセット
void ST7735_RESET(void) {
  digitalWrite(pin_RST, LOW);
  delay(10);
  digitalWrite(pin_RST, HIGH);
  delay(10);
}

 


◆ 初期化

基本的にはモノクログラフィック液晶等で学習した初期化手順と変わりないのですが、フルカラーなのでデータ量が多く1つの設定コマンドに複数のレジスタをセットする必要があります。

以下は初期化で使用するコマンドとその内容です。 全てのコマンドを書き出すと大きくなりすぎるので必要分のみ書き出します。

Instruction DC Command byte
7 6 5 4 3 2 1 0
FRMCTR1 - In Normal mode (full colors)
FRMCTR1 0 1 0 1 1 0 0 0 1 0xB1
RTNA set 1-line period 1 - - - - * * * * 0x01
FPA front porch 1 - - * * * * * * 0x2C
BPA back porch 1 - - * * * * * * 0x2D
FRMCTR2 - In Idle mode (8-colors)
FRMCTR2 0 1 0 1 1 0 0 1 0 0xB2
RTNB set 1-line period 1 - - - - * * * * 0x01
FPB front porch 1 - - * * * * * * 0x2C
BPB back porch 1 - - * * * * * * 0x2D
FRMCTR3 - In Partial mode + full colors
FRMCTR3 0 1 0 1 1 0 0 1 1 0xB3
RTNC set 1-line period 1 - - - - * * * * 0x01
FPC front porch 1 - - * * * * * * 0x2C
BPC back porch 1 - - * * * * * * 0x2D
RTND set 1-line period 1 - - - - * * * * 0x01
FPD front porch 1 - - * * * * * * 0x2C
BPD back porch 1 - - * * * * * * 0x2D

Frame Rate = fosc(333kHz) / ( ( RTNA + 20 ) x (LINE + FPA + BPA ) )

Instruction DC Command byte
7 6 5 4 3 2 1 0
INVCTRF - Display inversion control
INVCTR 0 1 0 1 1 0 1 0 0 0xB4
NLA set inversion 1 0 0 0 0 0 *     0x07
NLB   *  
NLC     *

0 で Line inversion、 1 で Frame inversion

A は Full-color Normal mode。 B は Idle mode。 C は Partial mode。

 

Instruction DC Command byte
7 6 5 4 3 2 1 0
PWCTR1 - Power control setting
PWCTR1 0 1 1 0 0 0 0 0 0 0xC0
VRH setting GVDD voltage 1 0 0 0 * * * * * 0xA2
IB 1 0 1 * * 0 0 0 0 0x02
SEL 1 0 1 * * 0 0 0 0 0x84
PWCTR2 - Power control setting
PWCTR2 0 1 1 0 0 0 0 0 1 0xC1
BT set VGH/VGL voltage 1 0 0 0 0 0 * * * 0xC5
PWCTR3 - In Normal mode (full colors)
PWCTR3 0 1 1 0 0 0 0 1 0 0xC2
APA adjust the operational amplifier 1 0 0 0 0 0 * * * 0x0A
1 0 0 0 0 0 0 0 0  
DCA adjust the booster voltage 1 0 0 0 0 0 * * * 0xC0
1 0 0 0 0 0 0 0 0  
PWCTR4 - In Idle mode (8-colors)
PWCTR4 0 1 1 0 0 0 0 1 1 0xC3
APB adjust the operational amplifier 1 0 0 0 0 0 * * * 0x8A
1 0 0 0 0 0 0 0 0  
DCB adjust the booster voltage 1 0 0 0 0 0 * * * 0x2A
1 0 0 0 0 0 0 0 0  
PWCTR5 - In Partial mode + full colors
PWCTR5 0 1 1 0 0 0 1 0 0 0xC4
APC adjust the operational amplifier 1 0 0 0 0 0 * * * 0x8A
DCC adjust the booster voltage 1 0 0 0 0 0 * * * 0xEE
VMCTR1 - VCOM control 1
VMCTR1 0 1 1 0 0 0 1 0 1 0xC5
VMH VCOMH voltage control 1 - - * * * * * * 0x0E
VML VCOML voltage control 1 - - * * * * * *  

 

Instruction DC Command byte
7 6 5 4 3 2 1 0
MADCTR - Memory data access control
MADCTL 0 0 0 1 1 0 1 1 0 0x36
MY Row address order 1 *           - - 0xC8
MX Column address order   *        
MV Row/Column Exchange     *      
ML Vertical Refresh order       *    
RGB RGB-BGR order         *  
MH Horizontal Refresh order           *

 

Instruction DC Command byte
7 6 5 4 3 2 1 0
GMCTRP1 - Gamma correction characteristics setting ('+' polarity)
GMCTRP1 0 1 1 1 0 0 0 0 0 0xE0
VRF0P High level adjustment 1 - - * * * * * * 0x02
VOS0P Low level adjustment 1 - - * * * * * * 0x1C
PK0P Mid level adjustment 1 - - * * * * * * 0x07
PK1P 1 - - * * * * * * 0x12
PK2P 1 - - * * * * * * 0x37
PK3P 1 - - * * * * * * 0x32
PK4P 1 - - * * * * * * 0x29
PK5P 1 - - * * * * * * 0x2D
PK6P 1 - - * * * * * * 0x29
PK7P 1 - - * * * * * * 0x25
PK8P 1 - - * * * * * * 0x2B
PK9P 1 - - * * * * * * 0x39
SELV0P 1 - - * * * * * * 0x00
SELV1P 1 - - * * * * * * 0x01
SELV62P 1 - - * * * * * * 0x03
SELV63P 1 - - * * * * * * 0x10
GMCTRN1 - Gamma correction characteristics setting ('-' polarity)
GMCTRN1 0 1 1 1 0 0 0 0 1 0xE1
VRF0P High level adjustment 1 - - * * * * * * 0x03
VOS0P Low level adjustment 1 - - * * * * * * 0x1D
PK0P Mid level adjustment 1 - - * * * * * * 0x07
PK1P 1 - - * * * * * * 0x06
PK2P 1 - - * * * * * * 0x2E
PK3P 1 - - * * * * * * 0x2C
PK4P 1 - - * * * * * * 0x29
PK5P 1 - - * * * * * * 0x2D
PK6P 1 - - * * * * * * 0x2E
PK7P 1 - - * * * * * * 0x2E
PK8P 1 - - * * * * * * 0x37
PK9P 1 - - * * * * * * 0x3F
SELV0P 1 - - * * * * * * 0x00
SELV1P 1 - - * * * * * * 0x00
SELV62P 1 - - * * * * * * 0x02
SELV63P 1 - - * * * * * * 0x10

 

Instruction DC Command byte
7 6 5 4 3 2 1 0
CASET - Column address set 表示範囲指定(横)
CASET 0 0 0 1 0 1 0 1 0 0x2A
XS X address start 1 XS15 ~ XS8 0x00
1 XS7 ~ XS0 0x02
XE X address end 1 XE15 ~ XE8 0x00
1 XE7 ~ XE0 0x81
RASET - Row address set 表示範囲指定(縦)
RASET 0 0 0 1 0 1 0 1 0 0x2B
YS Y address start 1 YS15 ~ YS8 0x00
1 YS7 ~ YS0 0x01
YE Y address end 1 YE15 ~ YE8 0x00
1 YE7 ~ YE0 0xA0
表示開始位置からのマージンがあり、X が 2ドットから 128ドット、Y が 1ドットから 160ドットの範囲の指定となる。

 

Instruction DC Command byte
7 6 5 4 3 2 1 0
COLMOD - Interface pixel format 色数/ビットフォーマットの設定
COLMOD 0 0 0 1 1 1 0 1 0 0x3A
IFPF Interface format 1 - - - - - * * * 0x05
IFPF  0x03 = 12-bit / pixel
      0x05 = 16-bit / pixel
      0x06 = 18-bit / pixel

 

//
// Div 005-02 初期化
//

void ST7735_INIT(void) {

  writeCommand(0x11); // Sleep out & booster on
  delay(120);

// ST7735R Frame Rate
  writeCommand(0xB1); // FRMCTR1 In Normal mode (full colors)
    writeData(0x01);
    writeData(0x2C);
    writeData(0x2D);
  writeCommand(0xB2); // FRMCTR2 In Idle mode (8-colors)
    writeData(0x01);
    writeData(0x2C);
    writeData(0x2D);
  writeCommand(0xB3); // FRMCTR3 In partial mode + full colors
    writeData(0x01);
    writeData(0x2C);
    writeData(0x2D);
    writeData(0x01);
    writeData(0x2C);
    writeData(0x2D);

// Column inversion
  writeCommand(0xB4); // INVCTR Display inversion control
    writeData(0x07);

// ST7735R Power Sequence
  writeCommand(0xC0); // PWCTR1 Power control setting
    writeData(0xA2);
    writeData(0x02);
    writeData(0x84);
  writeCommand(0xC1); // PWCTR2 Power control setting
    writeData(0xC5);
  writeCommand(0xC2); // PWCTR3 In normal mode
    writeData(0x0A);
    writeData(0x00);
  writeCommand(0xC3); // PWCTR4 In Idle mode (8-colors)
    writeData(0x8A);
    writeData(0x2A);
  writeCommand(0xC4); // PWCTR5 In parial mode + full-colors
    writeData(0x8A);
    writeData(0xEE);

// VCOM
  writeCommand(0xC5); // VMCTR1 VCOM control 1
    writeData(0x0E);

// MX, MY, RGB mode
  writeCommand(0x36); // MADCTL Memory data access control
    writeData(0xC8);

// ST7735R Gamma Sequence
  writeCommand(0xe0); // GMCTRP1 Gamma (+polarity) correction characteristics setting
    writeData(0x02);
    writeData(0x1c);
    writeData(0x07);
    writeData(0x12);
    writeData(0x37);
    writeData(0x32);
    writeData(0x29);
    writeData(0x2d);
    writeData(0x29);
    writeData(0x25);
    writeData(0x2b);
    writeData(0x39);
    writeData(0x00);
    writeData(0x01);
    writeData(0x03);
    writeData(0x10);
  writeCommand(0xe1); // GMCTRN1
    writeData(0x03);
    writeData(0x1d);
    writeData(0x07);
    writeData(0x06);
    writeData(0x2e);
    writeData(0x2c);
    writeData(0x29);
    writeData(0x2d);
    writeData(0x2e);
    writeData(0x2e);
    writeData(0x37);
    writeData(0x3f);
    writeData(0x00);
    writeData(0x00);
    writeData(0x02);
    writeData(0x10);
  writeCommand(0x2A); // CASET Column address set
    writeData(0x00);
    writeData(0x02);
    writeData(0x00);
    writeData(0x81);

  writeCommand(0x2B); // RASET Row address set
    writeData(0x00);
    writeData(0x01);
    writeData(0x00);
    writeData(0xA0);

  writeCommand(0x3A); // COLMOD
    writeData(0x05); 

// Display on
  writeCommand(0x29); // DISPON
}

◆ 初期化コマンドの詳細

Adafruit のライブラリと aitendo のサンプルプログラムで初期化の値が若干違っているので確認してみる。

  Adafruit aitendo
0x01 Software Reset delay(50); (Hardware Reset)
0x11 Sleep out & booster on delay(500);  
0x3A Set color mode 0x05 16-bit color
delay(10);
0x05
0xB1 Frame rate control
     In Normal mode (full colors)
Default Value
GM[2-0] = "000","011"
   RTNA =  02h , 02h
   FPA  =  2Ch , 2Dh
   BPA  =  2Dh , 2Eh
0x00 fastest refresh
0x06 6 lines front porch
0x03 3 lines back porch
delay(10);
RTNA = 0
FPA = 6
BPA = 3
0x01 set 1-line period
0x2C front porch
0x2D back porch
RTNA = 1
FPA = 44(2C)
BPA = 45(2D)
0xB2 In Idle mode (8-colors)
  0x01
0x2C
0x2D
0xB3 In partial mode + full colors
  0x01
0x2C
0x2D
0x01
0x2C
0x2D
0x36 Memory access ctrl
     MADCTL
0x08 Row addr/col addr,
     bottom to top refresh
MY  = 0
MX  = 0
MV  = 0
ML  = 0
RGB = 1  BGR color
MH  = 1  R -> L
 -- = 11
0xC8

MY  = 1  Row order
MX  = 1  Col order
MV  = 0  Exchange
ML  = 0  T -> B
RGB = 1  BGR color
MH  = 1  R -> L
 -- = 11
0xB6 Display settings #5
0x15 1 clk cycle nonoverlap,
     2 cycle gate rise,
     3 cycle osc equalize
 -- = 00
NO  = 01  2 clock cycle
SDT = 01  1 clock cycle
EQ  = 01  3 clock cycle
0x02 Fix on VTL
 
0xB4 Display inversion control 0x00 Line inversion  0x07
0xC0  Power control 0x02 GVDD = 4.7V
0x70 1.0uA
delay(10);
0xA2
0x02
0x84
0xC1 Power control 0x05 VGH = 14.7V,
     VGL = -7.35V
0xC5
0xC2 Power control
     In normal mode
   0x0A
0x00
0xC3 Power control
     In Idle mode 8-colors
0x01 Opamp current small
0x02 Boost frequency
0x8A
0x2A
0xC4 Power control
     In Partial mode full-colors
  0x8A
0xEE
0xC5 Power control 0x3C VCOMH = 4V
0x38 VCOML = -1.1V
delay(10);
0x0E
0xFC Power control 0x11
0x15
 
0xE0 Magical unicorn dust
     Gamma sequence
seriously though, not sure what these config values represent
0x09
0x16
0x09
0x20
0x21
0x1B
0x13
0x19
0x17
0x15
0x1E
0x2B
0x04
0x05
0x02
0x0E



0x02
0x1C
0x07
0x12
0x37
0x32
0x29
0x2D
0x29
0x25
0x2B
0x39
0x00
0x01
0x03
0x10
0xE1 Sparkles and rainbows  (ditto)
0x0B
0x14
0x08
0x1E
0x22
0x1D
0x18
0x1E
0x1B
0x1A
0x24
0x2B
0x06
0x06
0x02
0x0F
delay(10);

0x03
0x1D
0x07
0x06
0x2E
0x2C
0x29
0x2D
0x2e
0x2e
0x37
0x3F
0x00
0x00
0x02
0x10
0x2A Column addr set 0x00
0x02 XSTART = 2
0x00
0x81 XEND = 129
0x00
0x02
0x00
0x81
0x2B Row addr set 0x00
0x01 YSTART = 1
0x00
0xA0 YEND = 160
0x00
0x01
0x00
0xA0
0x13 Normal display on
     partial off
delay(10); (none)
0x29 Main screen turn on delay(500);  

自分は aitendo のサンプルで初期化した方が良い結果でした。


◆ 制御コマンド

Instruction DC Command byte HEX
7 6 5 4 3 2 1 0
Sleep in & booster off 0 0 0 0 1 0 0 0 0 10
Sleep out & booster on 0 0 0 0 1 0 0 0 1 11
Partial mode on 0 0 0 0 1 0 0 1 0 12
Partial off (Normal) 0 0 0 0 1 0 0 1 1 13
Display inversion off 0 0 0 1 0 0 0 0 0 20
Display inversion on 0 0 0 1 0 0 0 0 1 21
Gmma curve select 0 0 0 1 0 0 1 1 0 26
1 - - - - GC3 ~ GC0  
Display off 0 0 0 1 0 1 0 0 0 28
Display on 0 0 0 1 0 1 0 0 1 29
CASET 0 0 0 1 0 1 0 1 0 2A
1 X start address High byte  
1 X start address Low byte  
1 X end address Hight byte  
1 X end address Low byte  
RASET 0 0 0 1 0 1 0 1 1 2B
1 Y start address High byte  
1 Y start address Low byte  
1 Y end address Hight byte  
1 Y end address Low byte  
Memory write 0 0 0 1 0 1 1 0 0 2C
1 D7 ~ D0  

◆ 読取り系コマンド

Adafruit のライブラリをみるとデバイスからデータを読み取るコマンドがあります。 一応読み取り系のコマンドを書き出しておきます。

ただし、描画されているデータの読み取りコマンドが無いようなので、設定されているステータス等に限られているようです。

Instruction DC Command byte HEX
7 6 5 4 3 2 1 0
NOP - No Operation 0 0 0 0 0 0 0 0 0 00
SWRESET - Software Reset 0 0 0 0 0 0 0 0 1 01
RDDID Read Display ID 0 0 0 0 0 0 1 0 0 04
Dummy read 1 - - - - - - - - -
ID1 read 1 ID17 to ID10 (manufachurer ID)  
ID2 read 1 1 ID26 to ID20 (driver version ID)  
ID3 read 1 ID 37 to ID30 (driver ID)  
RDDST Read Display Status 0 0 0 0 0 1 0 0 1 09
Dummy read 1 - - - - - - - -  
 parameter 1 BSTON MY MX MV ML RGB MH 0  
parameter 1 0 IFPF IDMON PTLON SLOUT NORON  
parameter 1 ST15 0 INVON 0 0 DISON TEON GCS  
parameter 1 GCS TELON 0 0 0 0 0  
RDDPM Read Display Power 0 0 0 0 0 1 0 1 0 0A
Dummy read 1 - - - - - - - -  
parameter 1 BSTON IDMON PTLON SLPOUT NORON DISON - -  
RDD
MADCTL
Read Display 0 0 0 0 0 1 0 1 1 0B
Dummy read 1 - - - - - - - -  
parameter 1 MY MX MV ML RGB MH - -  
RDD
COLMOD
Read Display Pixcel 0 0 0 0 0 1 1 0 0 0C
Dummy read 1 - - - - - - - -  
parameter 1 0 0 0 0 - IFPF  
RDDIM Read Display Image 0 0 0 0 0 1 1 0 1 0D
Dummy read 1 - - - - - - - -  
parameter 1 0 0 INVON - - GCS  
RDDSM Read Display Signal 0 0 0 0 0 1 1 1 0 0E
Dummy read 1 - - - - - - - -  
parameter 1 TEON TELOM - - - - - -  
BSTON 0 = Booster off 1 = Booster on
MY 0 = Top to Bottom 1 = Bottom to Top
MX 0 = Left to Right 1 = Right to Left
MV 0 = Normal 1 = Exchange
ML 0 = refresh Top to Bottom 1 = refresh Bottom to Top
RGB 0 = RGB 1 = BGR
MH 0 = refresh Left to Right 1 = refresg Right to Left
IFPF 011 = 12-bit / pixel
101 = 16-bit / pixel
110 = 18-bit / pixel
IDMON 0 = Idle mode off 1 = Idle mode on
PTLON 0 = Partial mode off 1 = Partial mode on
SLOUT 0 = Sleep in 1 = Sleep out
NORON 0 = Partial Display 1 = Normal Display
ST15 0 = Scroll off 1 = Scroll on
INVON 0 = Inversion off 1 = Inversion on
DISON 0 = Display off 1 = Display on
TEON 0 = Tearing effect line off 1 = Tearing effect line on
GCS 000 = GC0
001 = GC1
010 = GC2
011 = GC3
TELON 0 = Tearing mode 1 1 = Tearing mode 2

◆ ピクセルデータのフォーマット

カラーディスプレイなので単純にオン/オフの制御ではなく、ピクセルを何色に設定するかを書き込みます。 消去という概念は無く黒で塗りつぶすという感じです。

本デバイスには、12-bits、16-bits、18-bits のカラーモードがあります。 

12-bit color は各色 4ビットで構成され 4096 色の表現ができます。ただし、8で割り切れないため、1ピクセル毎に4ビットずれることになります。連続したデータの書き込みにはビットシフト命令が必要になります。

16-bits color は R(5-bits)、G(6-bits)、B(5-bits)  で構成され 65536 色の表現ができます。 1ピクセル当たり 2バイト必要ですが、8で割り切れるため処理が解り易いものになります。

 18-bits color は 各色 6ビットで構成され 262144 色の表現ができます。 8で割り切れませんが各色の出力に 8ビットを使用するので、1ピクセル当たり 3 バイト必要になります。 解り易くはありますがデータが大きくなるので処理速度が犠牲となります。

12 bits color (2 pixel)
   D7    D6    D5    D4    D3    D2    D1    D0
    R3  R2  R1  R0  G3  G2  G1  G0
    B3  B2  B1  B0  R3  R2  R1  R0
    G3  G2  G1  G0  B3  B2  B1  B0

16 bits color (1 pixel)
   D7    D6    D5    D4    D3    D2    D1    D0
    R4  R2  R1  R1  R0  G5  G4  G3
    G2  G1  G0  B4  B3  B2  B1  B0

18 bits color (1 pixel)
   D7    D6    D5    D4    D3    D2    D1    D0
     -     -    R5  R4  R3  R2  R1  R0
     -     -    G5  G4  G3  G2  G1  G0
     -     -    B5  B4  B3  B2  B1  B0

◆ ピクセルの描画

モノクログラフィック液晶では縦 8ドットを 1ページとして 1バイトを 1ページとして描画したが、16 bits color で、1ドットあたり2バイトの転送を行う。

描画位置の指定は CASET と RASET で描画範囲を指定しなければならない。 描画のアドレスカウンターを指定するコマンドは無いようで、描画範囲を毎回指定しなければならない。

モノクログラフィック液晶で扱った文字データは 1 バイト = 1 ページ だったのでそのままでは使用できない。 ドットのオン/オフを判断して描画する必要がある。

また、消去の概念が無いので背景色を設定(把握)しておく必要があり、文字の描画の際には必ず色を設定しなければならない。

アドレスカウンターの移動方向は細かく指定することができます。 この指定を利用すると鏡文字や逆さ文字が同じデータを使用して表示することができます。 また、ディスプレイを横向きで使用する場合にも使用します。 以下はアドレスカウンターの増加方向の関係。

Direction MADCTL Image
B = begin / E = end
MV MX MY
Normal 0 0 0 (0,0) - (127,159)
Y-Mirror
上下反転
0 0 1  
X-Mirror
左右反転
0 1 0  
X/Y-Mirror
180度回転
0 1 1  
X/Y Exchange 1 0 0 フォントの LSBFISRT
X/Y Exchange
Y-Mirror
左90度回転
1 0 1 フォントの MSBFIRST
X/Y Exchange
X-Mirror
右90度回転
1 1 0  
X/Y Exchange
X/Y-Mirror
1 1 1  
MADCTL command
  writeCommand(0x36);
//MADCTL = MY - MX - MV - ML - RGB - MH - 0 - 0
            0    0    0    0    1     0   0   0 (Normal mode)
  writeData(0x08)
//  aitendo のサンプルでは 0xC8 になっている。
//  Exchange を行うと set Address Window も影響を受ける

◆ 簡単なグラフィック命令

いくつか簡単なグラフィック命令を作成する。既に描画されているデータを読み込めないので XOR での反転はできない。

//
// Div 005-03 簡単なグラフィック命令
//

// 描画範囲の指定
void setDrawWindow(byte x0, byte y0, byte xs, byte yx) {
  byte x1, y1;
  if ((xs - x0) >= 128) {
    x1 = 128 - x0;
  } else {
    x1 = x0 + xs;
  }
  if ((ys - y0) >= 160) {
    y1 = 160 - y0;
  } else {
    y1 = y0 + ys;
  }

  writeCommand(0x2A); // CASET
    writeData(0x00);
    writeData(0x02 + x0);
    writeData(0x00);
    writeData(0x02 + x1);
  writeCommand(0x2B); // RASET
    writeData(0x00);
    writeData(0x01 + y0);
    writeData(0x00);
    writeData(0x01 + y1);
  writeCommand(0x2C); // Memory write
}


// 描画範囲を初期値へ戻す
void setDefaultWindow(void) {
  writeCommand(0x2A);  // CASET
    writeData(0x00);
    writeData(0x02);
    writeData(0x00);
    writeData(0x81);
  writeCommand(0x2B);  // RASET
    writeData(0x00);
    writeData(0x01);
    writeData(0x00);
    writeData(0xA0);
  writeCommand(0x2C);  // Memory write
}

// 8色コード
unsigned int color8(byte color) {
  unsigned int c;
  switch (color) {
    case 0: // BLACK
      c = 0x0000; // 0b 00000 000000 00000;
      break;
    case 1: // BLUE
      c = 0x001F; // 0b 00000 000000 11111;
      break;
    case 2: // GREEN
      c = 0x07E0; // 0b 00000 111111 00000;
      break;
    case 3: // CYAN
      c = 0x07FF; // 0b 00000 111111 11111;
      break;
    case 4: // RED
      c = 0xF800; // 0b 11111 000000 00000;
      break;
    case 5: // MAGENTA
      c = 0xF81F; // 0b 11111 000000 11111;
      break;
    case 6: // YELLOW
      c = 0xFFC0; // 0b 11111 111111 00000;
      break;
    default: // WHITE
      c = 0xFFFF; // 0b 11111 111111 11111;
      break;
  }
  return(c);
}


// ピクセル描画
void setPixel(byte x, byte y, byte col) {
  unsigned int color = color8(col);
  setDrawWindow(x, y, 1, 1);
  writeData(color);
}

// 直線
void Line(byte x0, byte y0, byte x1, byte y1, byte col) {
  int xd = abs(x1 - x0);
  int yd = abs(y1 - y0);
  int xs = (x1 > x0) ? 1: -1;
  int ys = (y1 > y0) ? 1: -1;

  if (xd > yd) {
    int E = -xd;
    for (int i=0; i<xd; i++){
      setPixel(x0, y0, col);
      x0 += xs;
      E += 2 * yd;
      if (E >= 0) {
        y0 += ys;
        E -= 2 * xd;
      }
    }
  } else {
    int E = -yd;
    for (int i=0; i<yd; i++){
      setPixel(x0, y0, col);
      y0 += ys;
      E += 2 * xd;
      if (E >= 0) {
        x0 += xs;
        E -= 2 * yd;
      }
    }
  }
} 

// 四角
void Box(byte x0, byte y0, byte x1, byte y1, byte col) {
  Line(x0, y0, x1, y0, col);
  Line(x0, y1, x1, y1, col);
  Line(x0, y0, x0, y1, col);
  Line(x1, y0, x1, y1, col);
}

// 矩形塗りつぶし
void BoxFull(byte x0, byte y0, byte x1, byte y1, byte col) {
  if (x1 <= x0) return;
  if (x1 > 127) return;
  if (y1 <= y0) return;
  if (y1 > 159) return;
  byte xs = x1 - x0; 
  byte ys = y1 - y0;
  unsigned int color = color8(col);
  setDrawWindow(x0, y0, xs, ys);
  writeCommand(0x2C); // Memory write
  for (int i = 0; i <= xs; i++) {
    for (int j = 0; j <= ys; j++) {
      writeData(highByte(color));
      writeData(lowByte(color));
    }
  }
  setDefaultWindow();
}

// MADCTL
void setMADCTL(

MADCTL は、RGB のビットのみ既に表示されている画面に影響を与えます。


◆ 文字の表示

8 x 5 のフォントデータを使用して文字を表示してみる。 フォントデータはキャラクタ液晶でも使用していたものをそのまま使用する。

//
// Div 005-04 文字表示
//

static const char font[][5] PROGMEM = {
  { 0x00, 0x00, 0x00, 0x00, 0x00 },  // 20 (SPC)
  { 0x7e, 0x11, 0x11, 0x11, 0x7e },  // 41 A
  { 0x7f, 0x49, 0x49, 0x49, 0x36 },  // 42 B
  { 0x3e, 0x41, 0x41, 0x41, 0x22 },  // 43 C
  { 0x7f, 0x41, 0x41, 0x22, 0x1c },  // 44 D
  { 0x7f, 0x49, 0x49, 0x49, 0x41 }   // 45 E
};

void loop() {
  BoxFull(0,0,127,159,0);
  putChar(0,0,'A',7);
  tftPrint(5,10,"ABC",6);

  while(1);
}


// 一文字表示
void putChar(byte x, byte y, byte c, byte col) {
  byte dat;
  for (int i=0; i<5; i++) {
    dat = pgm_read_byte_near( &font[c-0x40][i]);
    for (int j=0; j<8; j++) {
      if ((dat >> j) & 1) setPixel(x+i,y+j,col);
    }
  }
}

// 文字列表示
void tftPrint(byte x, byte y, char *c, byte col) {
  while(*c) {
    putChar(x, y, *c++, col);
    x += 6;
  }
}

文字の表示ドットのみ描画しているので、ドットが点灯しない箇所では既に描画されているデータが表示されるので、表示位置を一度背景色で塗りつぶす操作が必要になる。

5 x 8 のフォントデータではかなり文字が小さいので 16 x 16 のデータでないと見づらい。