gc9a01pyはmicropython派にとって大変有難いライブラリだが、どれくらいの速度で描画できるのかが気になる。
Timerと組み合わせて、簡易的にFPSを調べてみる。
サマリは以下の通り。
関数 | 1回のdot数 | 式 | fps |
---|---|---|---|
line | 240 | tft.line(0, 0, 240, i, color565(i,255-i,count&255)) | 5fps |
line | 10 | tft.line(115, i, 125, i, color565(i,255-i,count&255)) | 106fps |
pixcel | 1 | tft.pixel(30+i, 30+j, color565(i,255-i,j)) | 948fps |
fill_rect | 1 | tft.fill_rect(30+i, 30+j, 1, 1, color565(i,255-i,j)) | 868fps |
fill_rect | 100 | tft.fill_rect(30+i, 30+j, 10, 10, color565(i,255-i,j)) | 755fps |
fill_rect | 240*240 | tft.fill_rect(0, 0, 240, 240, color565(i,255-i,j)) | 18fps |
line, pixelはdot数律速で、だいたい1秒1000dotが限界。
fill_rectは、SPIの命令送信と液晶内部処理の2つが律速。SPIの命令は最大1000回/s発行できる。
液晶内部での描画は、3パターンという少ない試行数からの試算なので意味があるかは怪しいが、今回の結果からは1dotあたり0.94usかかっていると推測される。
SPIの命令発行にかかる時間が変わらないとして、総塗り替えのときは1dotのときに比べ、54.4ms余分にかかっているので、1dotあたりに直すと0.94usとなる。
この結果を100dotに当てはめると803fpsとなり、実際のfpsに近い値になる。
試してみればいいことではあるが、fill_rectの速度推定にある程度役立つ。
以下は、実際に測定に使ったコードと結果の詳細。
■line:240dot
コードはこのような感じ。
# Timer、計測部分 from machine import Timer def showFPS(t): global count, count_prev, tft fps = count - count_prev tft.text(font,"FPS: {0}".format(fps),40,120,WHITE,BLACK) count_prev = count tim = Timer(period=1000, mode=Timer.PERIODIC, callback=showFPS)
# 描画部分 count = 0 count_prev = 0 while True: for i in range(240): count += 1 tft.line(0, 0, 240, i, color565(i,255-i,count&255))
この例は、直線描画の速度を調べている。
結果、ほぼ5fps。ごくまれに6になるときもあるが、無視してよいレベル。
■line:10dot
今度は、線分の式を「tft.line(115, i, 125, i, color565(i,255-i,count&255))
」に変えてみる。
結果、106fpsくらいまで性能向上する。
結果、106fpsくらいまで性能向上する。
lineの中身を見てみるとわかるが、これって結局pixelで1dotずつ描画指令を送信しているので、pixel数の多さで速度が決まるということだ。
このライブラリに限らず、なるべく1点ずつ打つのを避けないと、どんどん描画速度が下がってしまう。
■pixel
じゃあ、今度は1秒に何点打てるのか?を測ってみる。
while True: for i in range(180): for j in range(180): count += 1 tft.pixel(30+i, 30+j, color565(i,255-i,j))
見てみると、948点/s行けるようだ。
lineで10点ずつ打つと100fps→1000点/sで、240点ずつだと5fps→1200点/sなので、lineの結果ともマッチする。
lineで10点ずつ打つと100fps→1000点/sで、240点ずつだと5fps→1200点/sなので、lineの結果ともマッチする。
■fill_rect:1dot
次は、fill_rectを試す。vline, hline, rectも内部でこの式を呼び出している。
fill_rectは、液晶に対し開始終了地点と色を送るだけなので、実はpixelに比べてSPIで送る指示は2byteしか変わらず、送信回数は同じ。
もしSPIの送信がボトルネックとすれば、pixelと遜色ない速度が出せるはず。
次は、fill_rectを試す。vline, hline, rectも内部でこの式を呼び出している。
fill_rectは、液晶に対し開始終了地点と色を送るだけなので、実はpixelに比べてSPIで送る指示は2byteしか変わらず、送信回数は同じ。
もしSPIの送信がボトルネックとすれば、pixelと遜色ない速度が出せるはず。
while True: for i in range(180): for j in range(180): count += 1 tft.fill_rect(30+i, 30+j, 1, 1, color565(i,255-i,j))
結果、868fps前後となった。pixelに比べ、8.4%の性能低下で済んでいる。
これは1点ずつの描画だが、次は1回の描画面積が広くなっても変わらないか、試してみる。
■fill_rect:100dot
縦横を10ずつにして、1度に10dotずつ描画させてみる。
while True: for i in range(180): for j in range(180): count += 1 tft.fill_rect(30+i, 30+j, 10, 10, color565(i,255-i,j))
この場合は755 or 761fpsとなった。RP2040⇔GC9A01の間のSPIは変わらないが、液晶内部の描画が増えた分でこれだけ遅くなったということ。とはいえ13%の性能低下で、1回で更新できるdot数ベースならlineに比べて圧倒的に速い。
以上。
0 件のコメント:
コメントを投稿