Raspberry Pi PicoでPicoMite(MMBasic)を使う〜OLEDディスプレイへの出力

LCDディスプレイへの出力ができるようになったので次にI<sup>2</sup>Cベースのディスプレイを接続し、文字列およびグラフィックス出力を行なう。
# 使用する部品

Amazonで購入した[OLEDディスプレイ 0.96インチ 2個入り OLEDモジュール I2C 128X64 4ピン ホワイト Arduinoに対応](https://www.amazon.co.jp/dp/B0DJ7B8P48?ref=ppx_yo2ov_dt_b_fed_asin_title&th=1)を使用する。
このディスプレイは次のような特徴のOLEDディスプレイです。

- サイズ：0.96インチ
- 解像度：128×64ピクセル
- 表示色：白
# 配線

Radpberry Pi PicoとOLEDディスプレイは下記のピンを接続する。

| OLEDのピン | Picoのピン(物理ピン) |
| :-----: | :-----------: |
|   VDD   |    3V3(36)    |
|   GND   |    GND(3)     |
|   SDA   |   GP14(19)    |
|   SCL   |   GPD15(20)   |

# 実体配線図

配線は次の通り。

<!-- ここに配線図 -->
![OLED-PICO.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72921/45512d4e-266e-4069-8b90-9afb44646f63.png)


# システムI2Cポートとディスプレイチップの指定

PicoMiteがサポートするディスプレイやRTCなどのシステムデバイスを接続するI<sup>2</sup>CピンはコマンドプロンプトでOPTIONコマンドを使ってプログラムを実行する目に登録する必要がある。
また、今回利用するOLEDディスプレイのドライバSD1306はPicoMiteでサポートされているのでOPTIONコマンドでドライバチップを指定すればMMBasicのコマンドで容易に出力を制御できる。
システムで使用するI<sup>2</sup>Cピンとディスプレイのドライバチップの登録コマンドを次に示す。これらのコマンドはコマンドプロンプトで実行する。
```
システムデバイスを接続するI2Cポートの指定
> OPTION SYSTEM I2C GP14, GP15

ディスプレイのチップとディスプレイの向きの指定
> OPTION LCDPANEL SSD1306I2C, LANDSCAPE
```

- SSD1306I2Cは解像度128×64で初期化、SSD1306I2C32を指定すると解像度128×32で初期化されます
- ディスプレイの向きはLANDSCAPE（横向き）、PORTRAIT（縦向き）、RLANDSCAPE（逆さの横向き）またはRPORTRAIT（逆さの縦向き）のいずれかを指定します。これらは、L、P、RLまたはRPの短縮表記を利用できます

## 参考：LCDパネル設定を無効化

ディスプレイの向きを変更したい場合、次のコマンドで無効化し、再度設定する。

```
OPTION LCDPANEL DISABLE
```
# ディスプレイへの出力プログラム
ディスプレイの1行目に文字列Hello MMBasicをデフォルトのフォントで、2行目に文字列Helloをフォント番号2で、3行目に文字列worldをフォント番号3で表示するプログラムを以下に示す。

```BASIC
CLS                           ' Clear screen
Text 0,  0, "Hello MMBasic!"
Text 0, 12, "Hello!",, 2
Text 0, 32, "World!",, 3
```

Textコマンドは下記の代表的な描画コマンドに示すように指定した座標から文字列を指定したフォントで描画します。5番目の引数が文字列描画用のフォント番号です。フォント番号を指定しなかった場合はデフォルトのフォントが使われます。フォント番号は下記のフォント番号を参照してください。
座標はディスプレイの左上が(0, 0)でX軸は右方向が＋、Y軸は下方向が＋となる。

次のような表示が得られる。

![IMG_0915.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72921/1336a608-bc75-47c0-923b-fb14a31f7e85.jpeg)

今回使用しているOLEDディスプレイは白色のみなので色を指定しても白色しか表示できない。

# 代表的な描画コマンド
以下はPicoMiteユーザマニュアルに記載されている代表的な描画コマンドです。斜体の引数はオプションで省略可の鵜です。

| コマンド | 機能  |
| ---- | --- |
| CLS *C*    | 画面をC色にクリアします。<br>Cが指定されていない場合は、現在のデフォルトの背景色が使用されます。     |
| PIXEL X, Y, *C*  | ピクセルを光らせる。<br>Cが指定されていない場合は、現在のデフォルトの前景色が使用されます。           |
| LINE X1, Y1, X2, Y2, *LW*, *C*                                  | X1とY1から始まり、X2とY2で終わる線を描きます。<br>LWは線の幅で、水平線または垂直線にのみ有効です。指定されていない場合、または斜線の場合、デフォルトで1になります。斜線用の拡張バージョンがあります。|
| BOX X, Y, W, H, *LW*, *C*, *FILL*                               | XとYから始まり、幅Wピクセル、高さHピクセルのボックスを描画します。<br>LWはボックスの側面の幅で、ゼロにすることもできます。デフォルトは1です。<br>Cは線の、FILLは塗りつぶしの色の指定。 |
| RBOX X, Y, W, H, *R*, *C*, *FILL* | XとYから始まり、幅Wピクセル、高さHピクセルの角の丸いボックスを描画します。<br>Rはボックスの角の半径です。デフォルトは10です。 |
| CIRCLE X, Y, R, *LW*, *A*, *C*, *FILL* | XとYを中心とし、半径Rの円を描きます。<br>LWは、円を描く線の幅です。円周は0にすることができます(デフォルトは1)。<br>Aはアスペクト比で、浮動小数点数で、デフォルトは1です。たとえば、アスペクト比が0.5の場合、幅が高さの半分の楕円が描画されます。|
| TEXT X, Y, STRING, *ALIGNMENT*, *FONT*, *SCALE*, *C*, *BC*      | XとYから始まる文字列を表示します。<br>ALIGNMENTは0、1、または2文字です(文字列式または変数も使用できます)。最初の文字はXの水平方向の配置で、L(左揃え)、C(中央揃え)、R(右揃え)またはテキストの場合はLEFT、CENTER、またはRIGHTです。2番目の文字はYの垂直方向の配置で、T(上揃え)、M(中央揃え)、B(下揃え)またはテキストの場合はTOP、MIDDLE、またはBOTTOMです。デフォルトの配置はLEFT/TOPです。追加のコード文字を使用してテキストを回転できます。<br>FONTとSCALEはオプションで、デフォルトではFONTコマンドで設定されたものになります。<br>Cは描画色、BCは背景色です。オプションであり、デフォルトはCOLOURコマンドによって設定されたものになります。 |
| GUI BITMAP X, Y, BITS, *WIDTH*, *HEIGHT*, *SCALE*, *C*, *BC*    | XとYから始まるビットマップのビットを表示します。<br>HEIGHTとWIDTHはLCDパネルに表示されるビットマップの寸法で、デフォルトは8x8です。<br>SCALE、C、BCはTEXTコマンドの場合と同じです。ビットマップは整数または文字列変数または定数にすることができ、最初のバイトを最上行の最初のビットとして使用して描画されます(最初にビット7、次にビット6など)。その後に次のバイトが続きます。 |
| POLYGON n, xarray%(), yarray%() [, bordercolour] [, fillcolour] | xarray%()とyarray%()のn個のxy座標ペアを使用して、塗りつぶされたポリゴンまたはアウトラインポリゴンを描画します。<br>fillcolourが省略されている場合は、ポリゴンのアウトラインのみが描画されます。<br>bordercolourが省略されている場合は、現在のデフォルトの前景色がデフォルトになります。 |
| ARC x, y, r1, [r2], a1, a2 [, c] | 2つの放射状(度で定義)の間に、指定された色と幅の円弧を描きます。ARCコマンドのパラメータは、円弧の中心のx座標とy座標、内側と外側の半径、円弧の開始角度と終了角度、円弧の色です。0度の参照は12時の位置にあります。|

## フォント番号

MMBasicではテキスト描画に使用できるフォントは下表の8種類があり、Textコマンドの引数で指定する。

| フォント番号 | サイズ(幅x高さ) | キャラクターセット   | 説明   |
| :----: | :-------: | ----------------------------- | ---------------------------------- |
|   1    |   8x12    | 全95文字のASCII文字に加えて7FからFF（16進数） | 標準フォント（起動時のデフォルト）                  |
|   2    |   12x20   | 全95文字のASCII文字                 | 中サイズのフォント                          |
|   3    |   16x16   | 全95文字のASCII文字                 | VGAバージョン用の大きなフォント                  |
|   3    |   16x24   | 全95文字のASCII文字                 | HDMIバージョンとLCDパネル用の大きなフォント          |
|   4    |   10x16   | 全95文字のASCII文字に加えて7FからFF（16進数） | 拡張グラフィック文字のフォント。高解像度ディスプレイに適しています。 |
|   5    |   24x32   | 全95文字のASCII文字                 | 特大フォントで非常に鮮明です。                    |
|   6    |   32x50   | 0から9といくつかの記号                  | 数字、小数点、正負、等号、度、コロン記号。非常に分かりやすい     |
|   7    |    6x8    | 全95文字のASCII文字                 | 低解像度を使用する場合に便利な小さいフォントです。          |
|   8    |    4x6    | 全95文字のASCII文字                 | さらに小さいフォント                         |

日本語フォントは含まれていないため基本的には表示できないがMMBasicのフォントの定義機能を利用すれば表示可能である。

# ADT7410の測定結果をOLEDに表示する

## 配線

図のように配線した。

![OLED-ADT7410-PICO_ブレッドボード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72921/5e37558f-9157-4144-b1ea-7674caea72f4.png)

温度センサーADT7410の測定データをOLEDへ出力し、その棒グラフを描くプログラムは次の通り。


```BASIC
Dim data%(2), raw%, temp!, X% = 0, Y%            ' Define variables
Const TMP_ADDR = &H48                            ' Set ADT7410 I2C address
SetPin GP16, GP17, I2C                           ' Set ATD7410 I2C pin
I2C OPEN 100, 100                                ' Open I2C channel 1

Do
  I2C READ TMP_ADDR, 0, 2, data%()               ' Read temperature data
  raw% = data%(0) << 8 Or data%(1)               ' Convert temperature data
  raw% = raw% >> 3
  If raw% >= 4096 Then raw% = raw% - 8192
  temp! = raw% / 16.0
  Y% = Int(temp!)                                ' Get integer value
  stemp$ = Str$(temp!, 2, 1) + Chr$(&H60) + "C"  ' Make string of temperature
  Text 0, 0, stemp$,,3                           ' Write string to OLED
  Line X%, 63, X%, 63 - Y%                       ' Draw line
  Inc X%                                         ' Increment X
  If X% = 128 Then                               ' Check X coordinate rearch right edge
    Box 0, 24, 128, 40,,RGB(black), RGB(black)   ' clear graph area
    X% = 0                                       ' reset X coordinate 
  EndIf
  Pause 5000                                     ' Wait 5 sec
Loop

I2C CLOSE                                        ' Close I2C channel 1

End
```

- OLEDへ文字出力はフォント番号3を指定した
- 棒グラフはLINEコマンドで描画している
- 棒グラフを右端まで描いたら棒グラフの領域をBOXコマンドで黒く塗りつぶしてクリア
-
今回使用したOLEDは白色のみだがMMBasicでの色指定はRGB関数でRGBの値をそれぞれ8ビットで指定する方法`RGB(rdd, green, blue)`と色名を指定する方法`RGB(色名)`の二通りがある。

色名にはwhite(白)、black(黒)、blue(青)、green(緑)、cyan(シアン)、red(赤)、magenta(マゼンタ)、yellow(黄色)、brown(茶色)、white(白)、orange(オレンジ)、pink(ピンク)、gold(金)、salmon(サーモン)、beige(ベージュ)、lightgrey/lightray(ライトグレー)、grey/gray(グレー)が用意されている。

プログラムを実行すると次のような出力が得られる。

![IMG_0917.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72921/78598ed2-afeb-4a7a-9067-547b8eb196a0.jpeg)