TinyBASICプロジェクト
◆PCの原点、BASIC
70〜80年代からPCに触れた人が、必ず通った道がBASICだと思います。BASICの簡潔性が、専門家のものだったプログラミングを一般人に開放するのに大いに貢献したのは間違いないでしょう。
私も初めて持ったPCはAppleIIの完コピ品でした。今なら両手が後ろに回るヤツですが、当時は秋葉原でも堂々と売られていました。当時のPCは大体そうですが、AppleIIもシステムROM内にBASICを持っていて、電源オンと同時に使うことができました。またディスクシステムにもBASICが搭載されていて、BASICがOSのシェルコマンドになっていました。
(左:AppleIIの純正マニュアル類、中:DOSのマニュアルとBASICソースコード、右:AppleIIで日本語表示できるようにした)
BASICだけでもグラフィックを扱えたりそれなりに高度なことができるのですが、だんだん処理速度に不満が出て、アセンブラで機械語を使うようになりました。とはいえ素の機械語だけでハードウェアを扱うのは面倒なので、BASICの内部ルーチンを呼び出して利用するようになります。ソースコードを眺めてインタープリターの仕組みはおぼろげに理解していたのですが、深入りすることはなく、そのうちMS-DOSやPascalやCなどほかのOSと言語に興味が移ってしまいました。
その後仕事としてPCと向き合うようになり、仕事でVB.NETやVBAを使ってもあれがBASICとは思えず、BASICは記憶の地層の最下層に埋葬された状態になります。IchigoJamが出てきた当時も、何を今さらBASICという感想でした(すいませんすいません)
◆タイニーBASICをCで書く
数年前にこの本と出会って買ってしまったのも、記憶の最下層から何かが呼んでいたのかもしれません。しばらくは本棚の飾りになっていましたが、仕事に区切りをつけオノレの来し方行く末を考えるようになり、わが原点のBASICをおさらいする気になってきました。
この本で扱うのは著者の鈴木哲哉さんが作られた「豊四季タイニーBASIC」です。これは1976年のパロアルトタイニーBASICの言語仕様をベースに、Cでソースコードを書き直したものです。ソースコードはWindows、Linux、Arduino、PIC24Fの各バージョンが公開されていて、いずれもGNU GPLで利用できます。
この中で一番移植しやすそうで、遊べそうなのはArduino版です。Arduino系は手元に材料が山ほどあるし、自作したりそれなりに経験を積んでますしね。
◆Arduino互換機で動かしてみる
とりあえず手元のArduinoUNO互換機にソースコードを入れて動かしてみました。デフォルトでは入出力は、シリアル通信でPCのターミナルを使うのですが、それだとArduinoらしくないので、I2C-USBのアダプタでキーボードを繋ぎ、出力はシリアル接続できるレシートプリンタにしてみます。
なにやらテレタイプ感がありますが、ちゃんとBASICが動作しています。
しかし常時プリンタが出力だと用紙がもったいないので、何かディスプレイが欲しい。手元にあるOLEDを使ってみることにします。
OLEDを動かすのにAdafruitのライブラリを入れようとしたのですが、これが結構大きくて、タイニーBASICと合わせるとArduinoUNOのATmega328ではメモリに入りきりません。仕方がないのでATmega2560が乗った、Arduino MEGA互換ボードを使うことにします。
とりあえず表示はできますが、なんせ文字が小さいw。老眼には苦行です。
なので大きめのTFT2.8インチ液晶に変更です。液晶のライブラリのヘッダファイルがAdafruit純正と少し違っていて手こずりましたが、動きました。これで字が読めるようになります。
◆コマンドの拡張
オリジナルの豊四季タイニーBASICは最低限のコマンドしかサポートしていないため、せっかくあるArduinoのGPIOや、TFTのグラフィック機能を利用できません。というより、豊四季タイニーBASICはコマンドの独自拡張を前提に作られていますので、欲しいものを追加することにします。ここが、BASICインタープリターの仕組みを復習するという、このプロジェクトのキモになる部分です。
(オリジナルのBASIC命令群。これだけです↓)
豊四季タイニーBASICのArduino版は、tt_basic.inoとbasic.cppの2つのファイルで構成されます。tt_basic.inoはsetup()でボードや周辺デバイスの初期化をしたら、すぐloop()でbasic()を呼び出すだけです。
プログラムの本体になるのが、basic.cppの末尾にあるbasic()関数です。
これはBASICの入力プロンプトの後に入力された文字列を、先頭からキーワードテーブルと照合ながら、一つずつ中間コードに変換し、中間コードが命令であればその命令を定義した関数を実行します。
なので、コマンドを拡張するには、キーワードテーブル、中間コード、命令の機能を実行する関数、の3つをセットで拡張する必要があります。
↓(拡張したキーワードテーブル(左)と、それに対応する中間コード(右))
(TFTグラフィック命令の拡張の例。中間コードポインタを1つずつ進めることで、命令の後ろにある引数を取得します)
(サーボ命令の拡張の例)
結局、グラフィック、タッチスクリーン、ネオピクセル、サーボ、押しボタン、SD カードへのプログラムのセーブ・ロード、超音波センサーなど盛り込んでしまいました。
応用例として、超音波センサーをサーボで回して周辺の状況をグラフィック表示する、ソナーみたいなものをご覧ください。
(↓画像をクリックすると動画が見られます)
◆M5 Stackで動かしてみる
さてArduino MEGAでBASICマシンができたのですが、TFTやSDカードやUSBアダプタやボタンなどを追加することになりました。
よく考えるとM5 StackはSoCは違いますが、Arduino IDEが使えるのだから、タイニーBASICが移植できるんじゃね?ハードウェア用意する必要なかったんじゃね?
と今頃気づいたワタシは、さっそくM5 Stackに移植したのでした。w
(画像をクリックするとデモが表示されます)
ライブラリ周りをM5stack.hに入れ替えて、ライブラリ関数呼び出しを手直しすれば、Arduino版の仕様で大体そのまま実装できてしまいます。
M5はキーボードまで用意されているので、こっちの方が全然楽だったですね。w
グラフィック、プリンター、ボタン、SDカード、サウンド、GPIO(デジタル、アナログ、サーボ、ソナー)、一応Wifiも実装しました。ただタイニーBASICは文字列変数がないので、SSIDやURLなどが決め打ちになり、Wifiを使うには不十分です。文字列変数の実装もやりごたえがありますが、それはまたいずれ。
To be continued