藤本健のDigital Audio Laboratory
第992回
じゃじゃ馬に四苦八苦!? NEC「TK-80」互換キットで音を出してみた。後編
2023年7月10日 09:49
前回の記事では、ほぼ半世紀前の原始的なコンピュータ、NECのTK-80を再現するキット「ZK-80N」を紹介するとともに、実際に組み立てて動作するところまでを確認した。5×5のキーボードと7セグのLEDが8つのディスプレイだけ、というシンプルなものではあるが、個人的にかなりグッとくる機材だった。
後編の今回は、このキットを使ってプログラムを行ない、音が出るところまでトライしてみた。もっともプログラムといっても、いまのPythonのようなものではないし、JavaScriptでもなく、BASICでもCでもない。アセンブラとかマシン語という、ホントに原始的なプログラミング言語を使うしか手立てのない機材ではあるのだが、実際に音が出せるのかチャレンジしてみたい。
LEDをアキバで調達。スペーサーも取りつけハードは完成
ハンダ付けして組み立てた結果、とりあえず動作するまでにはなったが、非常に不安定で、ふとした拍子に暴走してしまう“じゃじゃ馬マシン”だった。が、ハンダ付けの怪しそうな部分をチェックし、再度はんだごてを当てたりした結果、安定した状態に持ってくることはできた。
一方で、LED不良があったことが判明。その後秋葉原に行って交換部品を購入。部品表には3mmのオレンジLEDと記載されていたが、店頭で見てみると3mmのものがオレンジのほかに赤、緑、青と4色あり、いずれも15円と安い。
せっかくなので、予備として、それぞれ2個ずつ購入して120円。一方、動作不安定を解消するためと基板そのものを安定させる目的で、基板の脚となるスペーサーも8セット購入し、まずはこれらを取り付けてみた。
前回、リード線を取り付けていたので、ここに各色のLEDを接続して、動作確認したところ、しっかり点灯することが分かった。この4色の中では青が一番明るくてキレイに思えたので、オリジナルのオレンジではなく、青色LEDを取り付けて、これでハードは完成だ。
いよいよプログラミングへ。PC経由で転送してみる
さて、ここからプログラミングに入っていくが、Z80のマシン語を書くのは本当に40年ぶりくらいだ。まずはマニュアルにあったプログラムをZK-80Nに直接打ち込んでみると、とりあえず動作することは確認できた。
が、こうしたサンプルプログラムを元に改編したり、自分で作ったプログラムをハンドアセンブルしてマシン語に変換し、それをZK-80Nに入力していく……というのは、なかなか気が遠くなる作業。しかしマニュアルを見てみると、パソコン経由でプログラムを転送する手段があるようなので、とりあえずこれを試してみることにした。
これを実行するには、USBでシリアル信号を入出力する機材をパソコンに取り付け、ターミナルソフトを使ってやり取りする必要があるようだ。
そういえば2年前、こどもパソコン「IchigoJam R」を取り上げた際、まさにUSBでシリアル信号をやりとりするUSB-シリアル変換アダプタを3個558円で購入したものが3つともそのまま残っていたので、これを使って試してみることにした。
ZK-80Nのシリアルポートには電源用の5VとGND、また送信用端子のTXと受信用端子のRXがあるのでこれをUSB側と接続する。その際、RXとTXをクロス接続させるのがミソ。この接続をすれば電源はこのシリアル接続で供給できるので、microUSBでの電源供給は切断するよう注意書きがあったので、そのようにしたところ、とりあえず電源が入ることまではOK。
その後、フリーウェアのターミナルソフトである「Tera Term」をダウンロードし、シリアル接続に設定した上で、通信速度を[115200bps]に設定する。
データは8bit、パリティはなし、ストップビットは1bitでフロー制御無しとしたところ、無事接続でき、プログラムをパソコンからZK-80Nに送れるようになった。
ただ、本来ZK-80Nを受信待機状態にすると、Tera Termには、[Start]と表示されるはずなのだが、文字化けになってしまう。
データを7bitにすると、しっかり[Start]と表示されるけれど、この状態ではうまくプログラムデータを送ることができない。文字化けはするけど8bitにすると、しっかり転送できるようだったので、今回は文字化けの原因はあまり追及せず、動かすこと優先で作業を進めていった。
ちなみに、テキストで書いたアセンブラのプログラムをマシン語に変換するのは、Web上のサービスである「JavaScript tiny assembler for PACHIPACHI computer」。ZK-80 miniの開発者であるKatsumi Morimatsuさんによる「電子ブロック工房」で提供されているものである。ここにアセンブラのプログラムを入力すると、マシン語が出力させるので、それをTera Termで転送してやればいい。
が、あまりにも久しぶり過ぎてアセンブラのコマンドなんか、まったく覚えていない。そういえば40年前まで使っていたものがあるはず、とNECのZ80変換表であるインストラクション活用表を引っ張り出してきて、これを見ながらプログラムにチャレンジを続ける。
5×5キーボードを鍵盤代わりに演奏してみたい
音より前に、まず最初に試してみたのは、7セグLEDに文字を表示させるというもの。
7セグLEDの各桁ごとアドレスが決まっていて、それぞれのアドレスにデータを送ることで表示を変えられるようになっているようだ。そこで、あえて16進数の数字ではない文字を表示させてみたのだ。それは前回の記事で触れた、懐かしのフレーズ「PLAY GOLF」という文字表示を実現させてみた。
ものすごく単純なことしかしていないのだが、こんな文字が表示できるだけで、楽しくなってくるのは、高校生のころに味わった感覚が呼び戻されたからだと思う。
さて、ここから目的の音を出すプログラムに入っていきたいと思うが、マニュアルを見ると、そのサンプルプログラムがあっさり見つかった。
ドレミファソラシドと演奏されるアセンブラのソースコードがあるので、これをパソコン上で入力し、マシン語に変換した上でZK-80Nに転送してやれば、うまくいくはずだ。
プログラムを入力し間違えると、マシン語への変換が正しくいかず、転送もできない。ここをしっかり行なった結果……あっさり演奏できてしまった。ZK-80Nの基板上に搭載されている圧電ブザーから音が聴こえた。
が、これだけでは面白くないので、もうちょっとオリジナルのプログラムに改編したいところ。シーケンスデータを入力して、演奏するようにするのもいけれど、せっかく5×5のキーボードがあるので、これを鍵盤代わりにして演奏できるようにしてみたい。
そこで、先ほどほぼ何も考えずに入力したプログラムを、改めてゆっくりチェックしていくと、思っていたのとずいぶん違った。
というのも、もともと予想していたのはOUT命令を使ってポートをオン/オフを繰り返すことで音を発生させるものだったのだが、ZK-80Nには、拡張システムコールなるものが用意されていて、そのルーチンを呼ぶだけで、さまざまなことが簡単にできてしまうのだ。
マニュアルを見ると、7種類の拡張システムコールがある。
この中に、まさに音程を出すためのPWM信号出力というものが用意されている。そして、そのPWM信号出力における引数としてBレジスタにポート番号、HLレジスタに周波数、DEレジスタにデューティー比を入れるだけで音が鳴らせるのだから、非常に便利。前述のサンプルプログラムも、まさにこれを使っていたのだ。
キーボード入力に関しては、TK-80がもともと持っていたシステムコールが2種類ある。1つはキーボードが押されるのを待って、何が押されたかを返すもの。もう1つは、どのキーが押されているかをスキャンして返すもの。ここでは後者を使って、キーボードを演奏できるようにプログラムを作ってみた。
【プログラム1】
21.txt(0.00MB) 755Byte
※編集部注:編集部ではプログラムの保証はいたしかねます。また、個別のご質問にはお答えできませんのでご了承下さい
たった、これだけのプログラムで動いてしまったのは感激だ。まあ、実際には、何度かバグがあって動作しなかったのだが、それでも15分ほどで完成して鳴らせたので、とても楽しくなってしまう。
が、ここには納得いかない問題があった。01210と順にキーを押してドレミレドと演奏するのは問題ないが、00のように0番のキーを押してドと鳴らして指を離したあとに、再度0を押すと発音しない。ほかのキーも同様で、同じキーを連続すると音が出ない。
どこかにミスがあるのでは? とプログラムをチェックしてみるも問題はなさそう。そこで、単純にドと鳴らして、音を止めた後、再度ドと同じ音を鳴らすプログラムを作ってみると、やはり音が出ないことが判明。
2回目においてデューティー比を変えるなど、違うパラメータにすればいいけれど、同じものだとダメなのだ。もしかしたら、音をストップさせる際のデューティー比を変更すればいいのでは…と試してみたけれど、これもダメ。
どうやら、拡張システムコールのバグというか仕様のよう。そこで、無理やりその問題を回避するプログラムに組みなおしたみた。もう少しスマートなプログラムの方法はありそうだけれど、とりあえず動いたので、今回はこれでよしとする。
【プログラム2】
22.txt(0.00MB) 1,107Byte
※編集部注:編集部ではプログラムの保証はいたしかねます。また、個別のご質問にはお答えできませんのでご了承下さい
ここでは基板上にある圧電ブザーで音を鳴らしていたわけだが、昨年、Arduinoでシンセを鳴らした際、簡単な回路を取り付けることでライン出力して、非常にキレイな音で鳴らせたので、そのときの回路を利用できるのでは? と接続してみる。
もともとZK-80Nではジャンパーピンで圧電ブザーとつないでいたので、これを取り外して、以前の回路と接続してみたところ、大成功。ちょっと演奏してみた映像がこちらだ。
聞いてみると分かるとおり、フロアノイズというか、無音時にキーンという音が出ているのが気になる。おそらく音を止める処理に問題があるように感じる。HLレジスタに0を入れてシステムコールすることで音が止まるはずだけど、実際には何らかが出ている、ということなのだろう。
そこで、030Aのシステムコールがどのようなプログラムなのか、覗いてみることにした。まあ、解析するのは容易じゃないだろうが、ハンド逆アセンブルを試みたのだ。
が見てみたらびっくり。「3E 82 D3 9E C9」とたった5バイトのプログラムになっていて、これを逆アセンブルすると「LD A,82」、「OUT 9E,A」、「RET」となっている。ホントかと思い、念のため同じコードを自分でサブルーチンとして設定して呼んでみたところ、同じ処理をしてくれた。
つまり、この辺はTK-80をそのままエミュレーションしているのではなく、9Eポートに82を出力すると、裏で何らかの処理を走らせるプログラムが仕掛けられているようだ。それによって、周波数とデューティー比を設定するだけで音が鳴らせるようになるらしい。
試しに、OUT命令をつかって音が鳴らせるかも試してみた。そもそも圧電ブザーがつながっているPORT2のポート番号が分からないので、手当たり次第試してみたり、プログラムを組んで00~FFの全ポートを総当たり戦で00とFFを交互に出力するようにしてみたけれど、ダメ。やはり何か普通ではない裏の処理をしているのだろう……というのが、とりあえず分かったことだ。
まだ、もうちょっと試してみたいこともあるけれど、マニアックになりすぎるし、キリがなさそうなので、今回はひとまずここまで。これだけ面白いものを開発してくれたKatsumi Morimatsuさんに感謝するとともに、それを製品化するとともに、いろいろと拡張してくれたピコソフトさんにも大感謝したい。