概要
ILI9341ライブラリはピクセルの書き込みを行う際、SPI通信を毎回開け直している。
そのため無駄な通信が多く、非常に遅くなっている。(下図)
ピクセルに書き込みを行っている関数を探し出し、それを使って描画コードを自作することで描画を高速化する。
なのでライブラリ内の図形描画や文字描画は早くならない。
他の液晶ライブラリも共通な部分が多いので、同じように高速化できる...かもしれない
環境
マイコン:teensy4.0
液晶:ILI9341搭載2.8インチSPI制御タッチパネル付TFT液晶 MSP2807
https://akizukidenshi.com/catalog/g/gM-16265/
ライブラリ:teensy用ILI9341ライブラリ ILI9341_t3.h (teensyduino入れた時についてきた)
手順
描画関数を特定する
105行あたりに drawpixel()関数がある。
void ILI9341_t3::drawPixel(int16_t x, int16_t y, uint16_t color)
{
if ((x < 0) || (x >= _width) || (y < 0) || (y >= _height))
return;
beginSPITransaction(_clock);
setAddr(x, y, x, y);
writecommand_cont(ILI9341_RAMWR);
writedata16_last(color);
endSPITransaction();
}
1pxだけ書き込んで、通信を終了している。
使う関数をpublicにする
drawPixel()内の関数を使いたいので使えるようにコードを改編する。
宣言されている場所に行き、protectedを消してpublicにしてしまう。
301行あたり
....
uint16_t measureTextWidth(const char *text, int chars = 0);
uint16_t measureTextHeight(const char *text, int chars = 0);
int16_t strPixelLen(char *str);
// protected: ←←←←←←←←←←←←←←←←←←←←←←←←←ここ
unsigned long _clock = ILI9341_SPICLOCK;
int16_t _width, _height; // Display w/h as modified by current rotation
int16_t cursor_x, cursor_y;
uint16_t textcolor, textbgcolor;
....
描画コードを自作する
canvasに描いたものを出力する。
canvas[x][y]=tft.color565(r,g,b); で描ける。
#include <ILI9341_t3.h>
#include <SPI.h>
#define TFT_DC 9
#define TFT_CS 10
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC);
void setup(){
Serial.begin(115200);
tft.begin();
tft.setClock(79999999); //ここは定格越えてて、動作するギリギリにしてある
tft.setRotation( 1 );
tft.fillScreen(ILI9341_BLACK);
}
short canvas[320][240];//二次元配列
void loop(){
static int count=0;
static int fps=0;
count++;
//draw canvas
tft.beginSPITransaction(tft._clock); //描画開始
tft.setAddr(0, 0, 320, 240); //書く範囲指定
tft.writecommand_cont(ILI9341_RAMWR); //書き込みコマンド???知らん
for(int y=0;y<240;y++){
for(int x=0;x<320;x++){
if(x==319 && y==239){//最後はwritedata16_last
tft.writedata16_last(canvas[x][y]);
tft.endSPITransaction(); //描画終了
}
else tft.writedata16_cont(canvas[x][y]); //ピクセル(x,y)描画
canvas[x][y]=tft.color565(0,0,0); //黒塗り初期化
}
}
// while(millis()-ftime <= 33); //fps固定
if((millis()-startTime) >= 1000){ //fps計算
startTime = millis();
Serial.print(count);
Serial.print("FPS ");
fps=count;
count=0;
}
}
おわり
書き込んでみる
SDカードから画像を読み込むコードを書いた。
もともと15fpsだったものが、45fps出るようになった。
せっかくなら60fps出したかったけど... ILI9341側がギリギリなのでできるのか分からん
1f前のcanvasと比較して、変化がないところはスキップする...とか?(FPS不安定になりそう)
↓これ作る時に使った
更新日 2023/02/02