ST7735R
https://www.aitendo.com/product/3858
この液晶モジュールを長いこと使い方がわからなくて部品箱のコヤシにしていたのだけど。
要はArduinoならライブラリ管理から入れられるAdafruit ST7735 and ST7789 Library を使えばいいんだよね、ということで動作確認。
→これ自体は商品ページ通りの配線でOK(たぶんRGBのフィールドだけ何かおかしい)
自分でSPI叩いてデータシートのコマンド投げてみたい、できればPIC32MXで使ってみたいという欲求を満たすには少々道のりが通そう。
とりあえず第一ステップとして、ライブラリを使わずにSPIで初期化して画面塗りつぶしてみるところから。
で、コマンドとデータをまとめて指定するための可変長引数の関数をつくったら、Arduinoの可変長変数の動きがおかしくてintでないとクラッシュするっぽい・・・つらい・・・
コードはこんな感じ。
void LCDCommand(byte cmd,...){
va_list ap;
va_start(ap, cmd);
digitalWrite(TFT_CS, LOW);
digitalWrite(TFT_DC, LOW);
SPI.transfer(cmd);
digitalWrite(TFT_DC, HIGH);
int cnt=va_arg(ap, int);
for(int i=0;i<cnt;i++){
byte data=(byte)va_arg(ap,int);
SPI.transfer(data);
}
digitalWrite(TFT_CS, HIGH);
va_end(ap);
}
初期化コード
LCDCommand(ST77XX_SWRESET,0);
delay(150);
LCDCommand(ST77XX_SLPOUT,0);
delay(500);
LCDCommand(ST7735_FRMCTR1,3,0x01, 0x2C, 0x2D);
LCDCommand(ST7735_FRMCTR2,3,0x01, 0x2C, 0x2D);
LCDCommand(ST7735_FRMCTR3,6,0x01, 0x2C, 0x2D,0x01, 0x2C, 0x2D);
LCDCommand(ST7735_INVCTR,1,0x07);
LCDCommand(ST7735_PWCTR1,3,0xA2,0x02,0x84);
LCDCommand(ST7735_PWCTR2,1,0xC5);
LCDCommand(ST7735_PWCTR3,2,0x0A,0x00);
LCDCommand(ST7735_PWCTR4,2,0x8A,0x2A);
LCDCommand(ST7735_PWCTR5,2,0x8A,0xEE);
LCDCommand(ST7735_VMCTR1,1,0x0E);
LCDCommand(ST77XX_INVOFF,0);
LCDCommand(ST77XX_MADCTL,1,0xC8);
LCDCommand(ST77XX_COLMOD,1,0x05);
LCDCommand( ST77XX_CASET, 4, // 1: Column addr set, 4 args, no delay:
0x00, 0x00, // XSTART = 0
0x00, 0x7F);
LCDCommand(ST77XX_RASET, 4, // 2: Row addr set, 4 args, no delay:
0x00, 0x00, // XSTART = 0
0x00, 0x9F);
LCDCommand(ST7735_GMCTRP1, 16 , // 1: Gamma Adjustments (pos. polarity), 16 args + delay:
0x02, 0x1c, 0x07, 0x12, // (Not entirely necessary, but provides
0x37, 0x32, 0x29, 0x2d, // accurate colors)
0x29, 0x25, 0x2B, 0x39,
0x00, 0x01, 0x03, 0x10);
LCDCommand(ST7735_GMCTRN1, 16 , // 2: Gamma Adjustments (neg. polarity), 16 args + delay:
0x03, 0x1d, 0x07, 0x06, // (Not entirely necessary, but provides
0x2E, 0x2C, 0x29, 0x2D, // accurate colors)
0x2E, 0x2E, 0x37, 0x3F,
0x00, 0x00, 0x02, 0x10);
LCDCommand(ST77XX_NORON,0);
delay(10);
LCDCommand(ST77XX_DISPON,0);
ついでにそれぞれ8bitのRGB値を、5-6-5bitに丸めつつ上位下位の値を作る感じの関数を。
byte RGB16h(byte R,byte G,byte B){
return R&0b11111000|(G&0b11100000)>>5;
}
byte RGB16l(byte R,byte G,byte B){
return (B&0b11111000)>>3|(G&0b00011100)<<3;
}
で、ここまでくると好きなRGB値で矩形描けるように。
void LCDFill(byte x1,byte y1,byte x2,byte y2,byte r,byte g,byte b){
LCDCommand(ST77XX_CASET,4,0,x1,0,x2);
LCDCommand(ST77XX_RASET,4,0,y1,0,y2);
digitalWrite(TFT_CS, LOW);
digitalWrite(TFT_DC, LOW);
SPI.transfer(ST77XX_RAMWR);
digitalWrite(TFT_DC, HIGH);
for(long i=0;i<(long)(x2-x1+1)*(long)(y2-y1+1);i++){
SPI.transfer(RGB16h(r,g,b));
SPI.transfer(RGB16l(r,g,b));
}
digitalWrite(TFT_CS, HIGH);
}
ちなみに、テストコードの最後にSPI.end()入れてたらなぜか液晶の端の方の表示がおかしくなる(白っぽくなる)ので最初メモリの埋め方が悪いのかと思って色々試してしまった。。。
I2CにつないだEEPROMからビットマップ画像(BMPファイルからヘッダ部分を削除したもの)を読み込んで液晶に表示するPIC32のサンプルをGithubに上げました
https://github.com/kinoppoid/LCDandEEPROM
※ピン名を設定すると自動生成されるマクロを使っています(あとでReadmeに書く)
久しぶりに同じことをしようと思ったら、ビットマップ画像を書き込むためのデータ変換の部分のやり方がわからなくなっていたのでメモ。
128*160ピクセルの24bitカラーのビットマップファイルを用意。
先頭54バイトを削除
バイナリからインテルHEXに変換できるツールで変換。
こんかいはこちらのページのものを使いました。
bin2hex xxxx.bmp > xxxx.hex
容量をギリギリに削る必要がないならbmpそのままROMに焼いて54バイト読み飛ばしてもいいかも。