次はもう一つのメインのプログラムである音を出す部分の検討だ。前述したように音を出すには,出力の周波数を変化させる。タイマ機能を利用して1波長の半分の時間をカウント,HighとLowを繰り返すことで,その音階に合った音が出力される。

 したがって,まずスピーカの出力をHighにした状態で,タイマ機能を使って1波長の半分の時間を測定。測定が終わったら割り込み機能を使って今度は出力をLowにして時間を測定。これを繰り返す,といったことを想定したのだが,よくよく分厚いマニュアルの中からタイマ機能部分を読んでみると,方形波を出力してくれる機能があることを発見。さらには,今回の実習においてスピーカを接続したP01から,まさに方形波が出力されることが分かった。初心者に対する問題だけに,そこまで難しくはなかったというわけだ。

図8 コンペア・レジスタにセットするカウント回数
図8 コンペア・レジスタにセットするカウント回数 (画像のクリックで拡大)

 従って,音階に合った周波数となるような間隔で方形波が出力されるようにセットすれば,スピーカからはその音が流れる。マニュアルを読むと,コンペア・レジスタと呼ばれるレジスタに,一つの方形波が出力されるまでにタイマがカウントする数を入力しておけばよいことが判明。そこで,仕様書に書かれた周波数から,コンペア・レジスタの入力すべき数を導いた。10進数を16進数で表す必要があったが,これはWindowsに付属の計算機が非常に簡単に変更してくれることを発見。さほど手間がかからなかった(図8)。

音を出していてもスイッチは常に監視

 どのスイッチが押されているかは,前段階のプログラムから分かる。音を出すプログラムでは,スイッチの音階に応じてコンペア・レジスタにデータをセットすれば良い。ただ,音を一度出せばそれで安心できるわけではなく,押されているスイッチが突然変わるかもしれない。すなわち常にどのスイッチが押されているかは監視し続けなくてはならない。そして違うスイッチが押されたならば,レジスタの値を変更して音を変える。その一方で同じスイッチが押されているならば,音を出す部分は変えずに,さらにスイッチを監視することを続けなくてはならない。

 このフローは結構ややこしいのだが,それぞれ音を出すフローの前に,前の音を比較する処理を挿入した。この処理を実行するために,音階を把握するためフラグをたてたアドレスを一旦ほかの場所に移し,このアドレスと新たにフラグがたてられたアドレスを比較する。一致すれば音を出す部分を回避して,再びスイッチの監視に入る。一致しなければ新たな数値をコンペア・レジスタに入れて音を変える(図9)。

図9
図9 メモリをチェックして音を出すフローチャート

 しかし,ここで一つ不具合が見つかった。スイッチが二つ押されているケースでは,エラーとして最初に戻すフローにしていたが,これでは音が出っぱなしになってしまう。そこで,スイッチが二つ押されている場合は,再度スイッチをチェックする前にコンペア・レジスタをクリアするようにした(図10)。

図10
図10 完成したフローチャート

 これで,一通りのフローチャートが完成したことになる。果たして本当にちゃんとしているのか。「何かスマートじゃないけど,素人らしくて良いんじゃない」と同僚が一応の合格点をくれた。確かに,苦労しただけに,これでプログラムが半分以上できたような気がする。実際にコードを書くと,絶対にうまくいかないだろうなー,ということも簡単に想像できる。ただ,ここまでくると,実際に音が出るようになるのが非常に楽しみになってきた。