音は出たけど…どうやってMIDI信号を受信すれば?

 取りあえず何かしらの音を出す部分は、課題のサウンド回路を拡張することで作成しました。サウンド回路はRAMから読んできたPCM波形を再生するモジュールですが、僕のハードウエアシンセサイザーではRAMとのやり取りは行わず内部から音を出すだけなので、決められた間隔(周波数)で0~1を繰り返す波形を作り、すぐに音が出ることを確かめることができました。

 次に、この音をコントロールすることを考えます。音色や発音タイミングを、FPGAボードにつないだMIDIキーボードで制御できるようにしたいので、MIDI信号を外部から取り込むための受信回路を作ります。

 MIDIとは、Musical Instrument Digital Interfaceの略で、電子楽器をコントロールするための規格です。

 MIDI信号は31.25kbpsの非同期シリアル信号なので、クロック信号はありません。1本の信号線のHIGH/LOWの状態だけを見て、それを意味のあるデータとして読み取っていくことになります。

 MIDIのプロトコルである、シリアルインターフェース(RS-232C)では、データは1byteずつひとまとまりになって送られてきます。1byteの頭は、スタートビットとストップビットという概念を用いて検出できるようになっています。

1byteずつひとまとまりとなって送られてくるデータ
[画像のクリックで拡大表示]

 データが送られていない時、基本的に信号はストップビットの状態(HIGH)になっています。1byteの一続きのデータの先頭には1bitのスタートビット(LOW)が付加されているので、受信する側はLOWを検知した段階で、「お、1byteきたな」と思って、受信ステートに移ります。ただし、もしかしたらこのLOWは単なるノイズかもしれません。そこで、何回かポーリングをして、31.25kbpsの1サイクル分がずっと0であることを確認します。

 上の処理で、このLOWがスタートビットで間違いないということになったら、そこから後の8bitが中身です。1bitずつ値を読んで、レジスターに貯めていきます。中身の次のbitは、ストップビット(HIGH)になっているはずなので、それを確認して、これで取りあえず1byte正しく受信できたということになります。

 次に、今度はこの中身の1byteを解釈する必要があります。MIDIプロトコルで送られてくる1byteにはステータスバイトとデータバイトの2種類があります。最上位ビット(MSB)が1の場合ステータスバイト、0の場合データバイトです。MIDIプロトコルでは、ステータスバイトがまず1byte送られてきたあと、そのステータスに応じて幾つか(基本的には二つ)のデータバイトが送られてくる、という決まりになっています。このステータスバイトと幾つかのデータバイトを合わせて、一つのMIDIメッセージということになります。なお、シリアル信号の受信方法に関しては、このサイトが参考になります。

ステータスバイトとデータバイト
[画像のクリックで拡大表示]