LoginSignup
3
0

More than 1 year has passed since last update.

ILI9341ライブラリ描画高速化

Posted at

概要

ILI9341ライブラリはピクセルの書き込みを行う際、SPI通信を毎回開け直している。
そのため無駄な通信が多く、非常に遅くなっている。(下図)
ピクセルに書き込みを行っている関数を探し出し、それを使って描画コードを自作することで描画を高速化する。
なのでライブラリ内の図形描画や文字描画は早くならない。

無題.png
(昔作った図)

他の液晶ライブラリも共通な部分が多いので、同じように高速化できる...かもしれない

環境

マイコン:teensy4.0

液晶:ILI9341搭載2.8インチSPI制御タッチパネル付TFT液晶 MSP2807
 https://akizukidenshi.com/catalog/g/gM-16265/

ライブラリ:teensy用ILI9341ライブラリ ILI9341_t3.h (teensyduino入れた時についてきた)

手順

描画関数を特定する

105行あたりに drawpixel()関数がある。

ILI9341_t3.cpp
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行あたり

ILI9341_t3.h
    ....
    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); で描ける。

main.ino
#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カードから画像を読み込むコードを書いた。
index.gif
もともと15fpsだったものが、45fps出るようになった。

せっかくなら60fps出したかったけど... ILI9341側がギリギリなのでできるのか分からん
1f前のcanvasと比較して、変化がないところはスキップする...とか?(FPS不安定になりそう)

↓これ作る時に使った

更新日 2023/02/02

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0