Raspberry Pi PicoでPicoMite(MMBasic)を使う〜LCDディスプレイを使う

PicoMiteのユーザマニュアルによるとPicoMiteはSPI、I2Cまたはパラレルインターフェイスによるディスプレイをサポートしているがここではコントローラがサポートされていない、ずいぶん前に購入したAQM0802を搭載したI<sup>2</sup>C接続のLCDへの文字列出力を行なうプログラムをユーザマニュアルやChatGPTを使いながら作成した。

# 使用する部品について
使用するLCDは2025年4月時点で販売終了しているスイッチサイエンスの [I2C controlled 8×2LCD Breakout for Raspberry Pi](https://www.switch-science.com/products/1516)です。
- 8文字2行の表示です。
- I<sup>2</sup>Cアドレスは`3E`です。


# 配線
LCDとRaspberry Pi PicoはADT7410の場合と同じピンに接続した。

| LCDのピン | Picoのピン(物理ピン番号) |
| :----: | :-------------: |
|  VDD   |     3V3(37)     |
|  SCL   |    GP17(22)     |
|  SDA   |    GP16(21)     |
|  GND   |     GND(38)     |

実体配線図は次の図の通り。
<!-- ここに配線図 -->
![AQM0802LCD_ブレッドボード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72921/4bf8914d-0ff8-43e1-8958-587a13c3ac41.png)


# LCD表示プログラム
MMBasicからAQM0802の1行目に文字列Helloを、2行目に半角でハローと表示するプログラムを作ります。
## 処理手順
1. LCDのI<sup>2</sup>Cアドレスの設定
2. I<sup>2</sup>Cで使用するRaspberry Pi Picoのピン指定
3. I<sup>2</sup>Cチャンネル1を開く
4. LCD(AQM0802)の初期化
5. 文字列Helloの出力
6. LCDのカーソルを2行目に移動
7. 半角カナでハローを出力
8. I<sup>2</sup>Cチャンネル1を閉じる
## MMBasicのプログラム
処理手順にしたがったプログラムを以下に示す。
先頭の11行が手順慰したがったコードでそれ以降はLCDの初期化、LCDへのコマンド送信、LCDへの文字列出力、LCDへのコードに対応した文字出力を行なうサブルーチンの定義。
```BASIC
Const LCD_ADDR = &H3E ' Define I2C address
SetPin GP4, GP5, I2C  ' Set I2C pin
I2C OPEN 100, 400     ' Open I2C
InitLCD               ' Initialize LCD
LCD_CMD &H01          ' Clear LCD
WriteString "Hello"   ' Write string
LCD_CMD &HC0          ' Move cursor next line
WriteChr &HCA         ' ha
WriteChr &HDB         ' ro
WriteChr &HB0         ' -
I2C CLOSE

' Subroutine:Initialize LCD
Sub InitLCD
  Pause 40
  LCD_CMD(&H38) : LCD_CMD(&H39)
  LCD_CMD(&H14) : LCD_CMD(&H70)
  LCD_CMD(&H56) : LCD_CMD(&H6C)
  Pause 200
  LCD_CMD(&H38) : LCD_CMD(&H0C)
  LCD_CMD(&H01)
  Pause 2
End Sub

' Subroutine:Write command
Sub LCD_CMD cmd 
  I2C WRITE LCD_ADDR, 0, 2, &H00, cmd
  Pause 2
End Sub

' Subroutine:Write string to LCD
Sub WriteString STR$
  For i = 1 To Len(STR$)
    I2C WRITE LCD_ADDR, 0, 2, &H40, Asc(Mid$(STR$, i, 1))
  Next i
End Sub

' Subroutine:Write the letter of the code
Sub WriteChr code%
  I2C WRITE LCD_ADDR, 0, 2 , &H40, code%
End Sub

```

### MMBasicのサブルーチン定義
MMBasicのサブルーチン定義はプログラム中にあるように、次の構文になる。
SUBで定義を始め、END SUBで終了する。
サブルーチンの引数は（）で囲んでも問題ない。

```BASIC
SUB サブルーチン名 引数1, 引数2, ...
  サブルーチンのコード
  ...
END SUB
```
### InitLCDサブルーチン
AQM0802の初期化のコードをLCD_CMDサブルーチンを使って順にLCDに送信している。
秋月電子通商のI2C接続小型キャラクターLCDモジュール 8×2行の[データシート](https://akizukidenshi.com/goodsaffix/AQM0802.pdf)に初期設定手順が示されている。

### LCD_CMDサブルーチン
`I2C WRITE`コマンドを使い、LCDにコマンドのコードを送信します。


    I2C WRITE I2Cアドレス, オプション, 送信データバイト数, データ1, データ2, ...

- オプションは0で通常モード、1でコマンド実行後にバス制御を維持する（ストップコンディションを送信しない）
- 送信データバイト数はコマンドとそれに対するデータ数の合計
- 送信データは&H00とサブルーチンの引数の2つ。
	- ＆H00はコマンド送信を意味する。

### WriteStringサブルーチン
引数で受取った文字列を一文字ずつ取り出し、アスキーコードに変換してLCDへ送信する。

- For文は通常のBASICと同じ
- LEN関数は引数の文字列の文字数を返す。
- ASC関数は引数の文字列の先頭文字のアスキーコードを返す。
- MID関数は1番目の引数の文字列から2番目の引数の位置の文字から3番目の引数分の文字を返す。
- &H40はデータ送信を意味する。

### WriteChrサブルーチン
引数で受取ったアスキーコードをLCDへ送信する。MMBasicでは半角かな文字を受け付けないのでLCDのアスキーコードテーブルを見てコードでLCDへ送信するために用意した。

# 実行結果
フルスクリーンエディタでプログラムを入力し、実行するとLCDにメッセージが表示される。

![IMG_0890.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72921/44ff9b27-b101-4fea-8cf0-1d6a8afdee3b.jpeg)

※ 上記の方法で秋月電子通商の[I2C接続小型キャラクターLCDモジュール(16×2行・3.3V/5V)ピッチ変換キット](https://akizukidenshi.com/catalog/g/g108896/)でも表示できる。