ORANGE pico での塗りつぶし line と gput を比較する

[ORANGE pico](http://www.picosoft.co.jp/orange/) における塗りつぶし処理4種類の速度を比較してみた。

# 今回の塗りつぶし処理

今回は、以下の4種類の塗りつぶし方法を比較する。

## line 横線

`line` コマンドを用い、横線を並べることで塗りつぶしを行う。
ループが必要だが、任意の大きさの長方形を簡単に描くことができる。
また、メモリー配列も消費しない。

## line 縦線

`line` コマンドを用い、縦線を並べることで塗りつぶしを行う。
ループが必要だが、任意の大きさの長方形を簡単に描くことができる。
また、メモリー配列も消費しない。

## gput ブロック

`gput` コマンドを用い、8×8ピクセルのブロックを並べることで塗りつぶしを行う。
自由度が「gput 一括」よりは高いが、幅や高さが8の倍数でない場合は処理が複雑になる。
若干ではあるがメモリー配列を消費する。
単純な実装では、二重ループを用いることになる。

## gput 一括

`gput` コマンドを用い、描きたい図形を一括で塗りつぶしを行う。
明示的なループは不要だが、一辺の長さが8の倍数の正方形しか描くことができない。
また、大きな正方形を描く場合、メモリー配列を大量に消費する。

# プログラム

塗りつぶし処理中 PORT1 に HIGH を出力することで、処理中を表す。
この時間を[ロジックアナライザ](https://www.switch-science.com/products/7642)で観測し、処理時間を求める。

```
10 white=rgb(255,255,255):x=0:y=0:width=200:height=200:waittime=10
20 ioctrl 1,0:out 1,0
30 ' ﾋｶｸ ﾖｳ
40 out 1,1
50 out 1,0
60 pause waittime
70 ' line ﾖｺｾﾝ
80 cls
90 out 1,1
100 for i=0 to height-1
110 line x,i,x+width-1,i,white
120 next
130 out 1,0
140 pause waittime
150 ' line ﾀﾃｾﾝ
160 cls
170 out 1,1
180 for i=0 to width-1
190 line i,y,i,y+height-1,white
200 next
210 out 1,0
220 pause waittime
230 ' gput ﾌﾞﾛｯｸ
240 cls
250 out 1,1
260 mset 0,&HFF,8
270 for i=0 to height-1 step 8
280 for j=0 to width-1 step 8
290 gput x+j,y+i,8,0,white
300 next
310 next
320 out 1,0
330 pause waittime
340 ' gput ｲｯｶﾂ
350 cls
360 out 1,1
370 mset 0,&HFF,width/8*height
380 gput x,y,width,0,white
390 out 1,0
400 pause waittime
```

このプログラムは、[CC0 1.0](https://creativecommons.org/publicdomain/zero/1.0/deed.ja) でライセンスする。

# 計測結果

前述の4種の方法に加え、「比較用」としてポートの操作のみを行い、その時間も測定した。
3回測定し、平均をとった。
以下の表の時間の単位はμsである。
「平均 - 比較用」の値は、それぞれのモード・描画方法の平均から「比較用」の平均を引いた値である。
グラフは、「平均 - 比較用」の値を図持したものである。

## ビデオ出力モード (spitft 0)

|描画方法|計測1|計測2|計測3|平均|平均 - 比較用|
|---|--:|--:|--:|--:|--:|
|比較用|32.71|32.71|23.17|29.53|0.00|
|line 横線|74188.50|74187.38|73454.96|73943.61|73914.08|
|line 縦線|76882.17|76882.92|75017.46|76260.85|76231.32|
|gput ブロック|129867.71|129872.33|131049.67|130263.24|130233.71|
|gput 一括|35812.33|35813.08|37261.54|36295.65|36266.12|

![ビデオ出力モード 各方法の比較](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/cc236105-cde9-f0c0-76d3-1e0e05fe24cc.png)


## TFT液晶横型モード (spitft 1)

|描画方法|計測1|計測2|計測3|平均|平均 - 比較用|
|---|--:|--:|--:|--:|--:|
|比較用|21.58|21.63|23.46|22.22|0.00|
|line 横線|549071.54|548962.04|548929.25|548987.61|548965.39|
|line 縦線|550706.63|550737.08|550735.75|550726.49|550704.27|
|gput ブロック|594979.00|595007.42|595015.83|595000.75|594978.53|
|gput 一括|526696.50|526723.83|526693.08|526704.47|526682.25|

![TFT液晶横型モード 各方法の比較](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/145a1548-3e03-25e4-d608-1b08c94892ae.png)

## TFT液晶縦型モード (spitft 4)

|描画方法|計測1|計測2|計測3|平均|平均 - 比較用|
|---|--:|--:|--:|--:|--:|
|比較用|23.46|21.58|23.46|22.83|0.00|
|line 横線|548888.67|548933.13|548912.54|548911.45|548888.62|
|line 縦線|550679.96|550718.75|550706.54|550701.75|550678.92|
|gput ブロック|594913.63|595006.42|594993.29|594971.11|594948.28|
|gput 一括|526653.25|526714.25|526666.79|526678.10|526655.27|

![TFT液晶縦型モード 各方法の比較](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/6cf54ec9-bfd2-7780-7d02-71ab0ec736ae.png)

# 考察

今回実験を行ったすべてのモードについて、明示的なループを行わない「gput 一括」の処理時間が一番短かった。
メモリー配列の容量や描画したい形などの条件が合い、うまく適用できる状況であれば、これを使うのが一番よい可能性がある。

次いで「line 横線」の処理時間が短く、僅差で「line 縦線」が続いた。
TFT液晶の向きを変えてもこの大小関係は変わらず、あまり関係ないと推測できる。
[以前の記事](https://qiita.com/mikecat_mixc/items/d996fa4493bf1a1d30fc)で、変数の情報が格納された領域が線形リストのようになっている可能性を示した。
そのため、縦線と横線の違いではなく、変数 `width` と `height` がメモリに格納されている順番の違いが処理時間の違いに繋がった可能性が考えられる。

最後に、「gput ブロック」の処理時間が一番長かった。
二重ループになりやすい、幅や高さが8の倍数以外では難しいなどの欠点もあり、この方法を使うくらいなら `line` コマンドを用いる方法のほうがよいだろう。