ラズピコのMicroPythonで、以前作成したST7735ドライバやFBConsoleの動作テストをしてみました。ST7735ドライバは広く使われているTFT LCDモジュールのコントローラチップのドライバ、FBConsoleは任意のFrameBuffer互換のデバイスをREPLの出力先として利用できるようにするクラスです。
結果、両方ともコード自体は変更の必要なく動作するのですが、FBConsoleについてはこれを利用するためのdupterm()が動きません。
【2023/5/17追記】現在のMicroPython v1.20.0 (2023-04-26) .uf2 はdupterm()をサポートしています。
この機能は、
uos.dupterm(object)
とすると、objectに対してREPLの入出力が行われるようになるものです。objectは文字列描画やスクロール、REPLで使われれるエスケープシーケンス等を処理できる必要があります。簡単に言うと、objectを実装するのは簡易的なターミナルエミュレータを実装するようなものです。FBConsoleは、FrameBufferクラスの文字描画機能等を使ってこれを実装しています。
今回は、そもそもdupterm()が動作しませんでした。調べてみたところ、
・PicoのMicroPythonは、デフォルトではdupterm()は無効になっている
・dupterm()を有効にしても、REPLのデータをdupterm()で指定されたデバイスに送ってくれない
という2つの原因がありました。
前者については、uosモジュールの中でdupterm()メソッドが
#if MICROPY_PY_OS_DUPTERM
#endif
で囲われており、かつMICROPY_PY_OS_DUPTERMは偽になっています。
MICROPY_PY_OS_DUPTERMの値を設定するには、CMakeLists.txtのtarget_compile_optionsに
-DMICROPY_PY_OS_DUPTERM=1
を追加することで有効化できます。あるいは、
env CFLAGS="-DMICROPY_PY_OS_DUPTERM=1" cmake . -B build
のようにすると、環境変数経由で無理やり設定することができます。
後者については、そもそも実装されていなかったので、コードの修正が必要でした。
mphalport.cの中で定義されている、REPLの文字列出力を行う関数mp_hal_stdout_tx_strn()の中で、REPLの出力文字列をdupterm()で指定されたオブジェクト(上の図のdupterm_objs)にも送る必要があります。そのための関数はmp_uos_dupterm_tx_strn()です。(以前、こちらの記事で少し触れていました。)
今回この部分が実装されていなかったので、mp_uos_dupterm_tx_strn()の呼び出しをmp_hal_stdout_tx_strn()に追加することで、FBConsoleが動作するようになりました。
ごく僅かな修正ではありますが、プルリクエストを投げてあります。
もっとも、Picoで推奨されるIDEであるThonnyはdupterm()向きではありません。ThonnyはREPLではなくraw REPLを使用し、人間には見せない形でMicroPython処理系とデータをやりとりしています。dupterm()を使うと、その生のデータがduptermデバイスに送られてしまいますので、Thonnyを使っている環境でduptermを使うとユーザは混乱するかもしれません。
I2C接続のSSD1306にREPLを出力する場合のコードと接続の例は、こんな感じになります。
また、SPI接続のST7735 LCDにREPLを出力する場合のコードと接続の例は、こんな感じになります。
なお
'ST7735.py', 'ST7735fb.py', 'fbconsole.py', 'petme128.py', 'ssd1306.py'
の各ファイルは、あらかじめMicroPython側のファイルシステムに転送してある想定です。(またはCtrl-E/Ctrl-DによるPaste Modeを使って直接読み込ませておいても良いです。)ファイルの転送はThonnyが使えますが、duptermの実験自体には前述のようにThonnyはあまり向いていませんので、TeraTermなどの通信ソフトを使用してください。
duptermから抜けるには
uos.dupterm(None)
です。
コメント