PIC AVR 工作室->TopPage->AVRの工作->UART-MIDI変換

TINY2313でUARTとMIDIの変換

前置き

MIDI接続の今と昔

最近のMIDI機器は既にUSB化されて久しいのですが、残念なことに私の手元にはUSB化されていない機器がいっぱい残ってます。

昔のPCであれば、サウンドブラスターのボードに登載されたゲームポートがあれば、 単純な変換ケーブルで繋ぐだけでPCとMIDI機器が簡単に接続できたのですけど、最近のPCにはこのゲームポートも付いてません。

例えばこれはウチにあるおもちゃのMIDIキーボードの背面写真です。

左側にある丸い端子がそれぞれMIDI-IN、MIDI-OUT。普通ならここに各種のMIDI機器をズラズラと直列的に簡単に繋げちゃう。 MIDI-OUTをMIDI-INにズラズラつないでいく分には迷うことなし。

って具合に、昔ながらのMIDI信号はマイコンでも扱いが簡単な一方通行のシリアルi/fの規格なのに対し、USB機器は扱いがかなり面倒です。 USBは片方向のI/Fじゃなくて「バス」だから、扱いがちょっと変わっちゃう…。パッケージ的にはKORGのnanoKEYなんかとても魅力的なのに…。

なんとかして繋ぎたい

市販のUSB-MIDI変換ケーブルを使えば旧来のMIDI機器も比較的簡単にPCと接続することが出来るのは承知の上なんだけど、 OSやPCの型が新しくなる毎に付属品まで一緒に買い換えさせられるのはなんとなく癪だしイヤ。

そもそもMIDIケーブル上を流れる信号はシンプルな8n1のシリアル信号(マイコンのUARTで扱うシリアル信号と同じ) フォーマットなので、マイコンで扱うにはもってこいです。実際マイコンとMIDI機器を接続する製作例はたくさん公開されています。

マイコンでこういうMIDI関係の工作をする際、 工作物のテストをする際にPC上でやり取りする信号をモニタできれば作業も捗るかなぁとかたくらんでます。 USB-MIDI変換ケーブルじゃぁシリアル接続ほど簡単にモニターできそうに無いからやっぱりヤダ。

というわけで、なんとかシリアルケーブル経由でMIDI機器と接続したいと妄想していました。

写真の左から3つ目の丸い端子…一般にTO HOSTとかかれているミニDIN8ピン端子…は、PCとRS232C経由で接続するためのコネクタです。 この端子には論理的にはMIDIと同じ信号が流れていています。(速度が異なりますが)

このTO HOST端子はすべてのMIDI機器に付いているわけでは有りませんから、MIDI機器側は通常のMIDI端子(DIN5ピン)を使い、 PC側はシリアル端子(いわゆる9ピンRS232C)に接続する…という方向で。

なぜ速度が違うのか

そもそもPIC等のマイコン類であればMIDI信号を扱うことは造作無いのですが、PCのシリアル端子(いわゆる9ピンのRS232C) は制御チップの仕様制約により、同じ8n1であってもMIDIと同じ速度の通信が出来ません。 9600bpsや115200bpsなど数種類の決められた速度から選択することしか出来ないためです。

そのため、各MIDI楽器メーカー謹製のシリアルMIDIドライバ(MIDI音源の背面などにTO HOST端子が登載されている場合に使うドライバ) もこの仕様によってMIDIの通信速度に近い38400bpsとなっているようです。

ということで通常のMIDI信号は31250bps、PCのシリアル端子(とTO HOST端子)で扱う信号は38400bps(※)と、速度の点で互換性がありません。 (※:実際は繋ぐPCやMIDI機器によって異なるので一概には言えませんが…)

逆にいうと、速度の変換さえ出来てしまえば電気的には回路の作り方次第でなんとでもなってしまうはずです。

作戦

速度を変換しちゃえばいいだろう…と

ハードウェアUSART登載のマイコンであればシリアルI/Oの速度をある程度自由自在に設定できます。当然31250bpsも38400bpsも。 このマイコンを使って速度変換機能を実現し、MIDI機器とPCの間に挟み込めばシリアル端子経由でMIDI機器と接続可能なはずです。

そうすれば、例えばwindowsのmediaplayerでMIDIファイルを再生しつつ、 それを9ピンシリアル端子経由で旧来のMIDI音源に繋いで鳴らすことも出来ちゃうし、 MIDIマスターキーボードからwindows上のシーケンサソフトに演奏の信号を読み込むことも出来ちゃいます。

そういうわけで、マイコンを使って市販のUSB-MIDI変換器よりも安上がりの速度変換器を作ってみることにします。 といっても部品代全部合わせて1000円近く行くかなぁ…

なお、盛り込む機能は通信速度の変換だけです。MIDI関係のi/fという意味では、 お手持ちの各MIDI機器のメーカーさんご提供の「シリアルMIDIドライバ」をそのまま使うことにします。 ヤマハ、ローランドなどなど各メーカーからシリアルMIDIドライバが公開されています。

そういうわけでマイコンで速度変換を行いつつ、各メーカーのシリアルMIDIドライバを組み合わせる作戦を考えます。

注意点

実際に出来上がりを接続してみて判った注意点を。

PC本体背面に登載された9ピンシリアル端子であれば特に何の問題も起こらないと思いますが、 注意を要するのは「USB-シリアル変換ケーブル」経由で接続する場合です。

各MIDI機器メーカー提供のシリアルMIDIドライバが、USB-シリアル変換ケーブル経由に対応出来ているか否かによって影響したり、 USB-シリアル変換ケーブルのドライバとの相性によっても影響されるようです。

ちなみにウチの環境の話。PC背面の9ピンシリアル端子経由であれば当然何の問題もなく機能しました。 が一方、windows機にヤマハ製シリアルMIDIドライバを組み込み、 USB端子にATEN製のUSB-シリアル変換器を使用したところ、ウンともスンとも言いませんでした。

ちなみに単純な変換ケーブルと違ってマイコンの駆動に電源が必要になります。なのでUSB接続が出来なくなっちゃうと、常時接続しておいて使うよりは、 やはりマイコンでMIDI関係の工作をする際のモニター的な用途程度になっちゃう。なんとかUSB接続したい…

このあたりについては後日いろいろ実験したので、その結果を下のほうに書いておきます。ドライバのメーカーによって動いたり、動かなかったり…

スペックを考えてみる

方向性

盛り込むべきは速度の変換処理だけなので、プログラム的には大した話じゃありません。 強いて言えば、速度変換の観点…特にPC→MIDI機器方向…の通信では送り出し側が速く受け側が遅いので、 一定量のバッファリングが必要になるということが注意点でしょうか。

一方、ハードウェア的にはMIDIの規格にきちんと合わせないと接続するMIDI機器をぶっ壊す恐れがあるので、 この辺りは情報をきちんと整理して練りこんでいきたいところ。

この辺りを考慮しつつ、一方仕様がころころ変わるモノでもないので、必要最低限のマイコンを選出し、 適当な回路とプログラムをでっち上げていくことにします。

仕様検討1:通信経路とマイコンの選択

上に挙げた概略図の通り、シリアルの入力・出力がそれぞれ2つずつあり、しかもPC側・MIDI側では速度が異なります。 これをマトモに満たすマイコンを探すと、AVRならUSARTを2個登載したmega128とかmega64のような規模の大きなやつばかり。 似たようなモノでもmega644PはUSARTが1個しか入ってません。

最初は手元のmega128を使っちゃおうかと思ったんですが、何しろやっぱり勿体無い…。 巨大なプログラムメモリの殆どが使われずじまいになっちゃう…

アタマを切り替えて、入力側の経路、出力側の経路を2つのマイコンに分けたらどうか…。 オイラの大好きなtiny2313なら1個100円程度だし、USARTも登載しているし。いけるんじゃないかな?

…でも1つだけ問題アリ。

USARTが2個入っているマイコンなら2つの速度を混在させることができるので、そのうち入出力のペアをPC側に、 もう一つのペアをMIDI側に充てることができるけど、マイコンを2個に分けちゃうとハードウェアUSARTで扱える速度は1種類のみ。 ハードウェアだけでは速度変換が出来なくなっちゃう…

気を取り直して。

入力側をソフトウェアで行うとなると正確なタイミングで全二重動作させるのは難しくなるので、 入力側についてはハードウェアUSARTを使わざるをえないえしょう。一方、入力をハードウェアに任せて置けば、 出力側だけならポーリングでやっちゃうのは造作無いでしょう。

そしていずれにしてもMIDI→PC側の経路はバッファリングが必要になるので、それらを踏まえると…

こんな感じでしょうか。この橙色のところをそれぞれtiny2313を充てるというわけ。

仕様検討2:ストックとフロー

流出入するデータのストックとフローについて考えます。観点は2つ。MIDI-INから受けてPCに抜けていくルートと、 PCから受けてMIDI-OUTに抜けていくルートの2つ。

まずはMIDI-INから受けてPCに抜けていくルートの方。こっちはシンプル。

MIDI-INから入ってくる速度は31250bps。対してPCに抜けていく速度は38400bps。 入ってきたデータは即時出力し、かつ出力の方が速いという事になるので、ストックは不要ですね(といっても最大で1バイトはストックする)。 フローは最大で31250bps、つまり遅い方のMIDI-INに引きずられるカタチになります。 1バイト入力してから次の1バイトを入力するまでの間に出力処理は完了してしまうわけです。

もう一つの方。PCから受けてMIDI-OUTに抜けていく方。こっちは厄介。

PCから入ってくる速度は38400bps。対してMIDI-OUTに抜けていく速度は31250bps。フン詰まりになってます。 PCから連続してデータが入りつづけたら永遠にデータが処理し終わらずに溜まりつづけていくことになります。

さて、ホントにそんな事になるのかというと、実際はそういうことではありません。 MIDIデータのトラフィックは、基本的には「音が出始めたよ」とか「音が止まったよ」という合図。 なので音符と音符の間は比較的閑散としているはずです。ある程度のバッファを確保しておきつつ、 場合によってはフロー制御も組み合わせて使えば良いことになります。

ちなみに私が参考にしたこのサイト によると、ローランド、カワイ、ヤマハはハードウェアフロー制御を用いてますが、コルグの回路を見るとフロー制御を行ってません。

つまり閑散としたデータゆえ、ある程度のバッファを確保すればフロー制御は要らないってことと考えて良さそうです。

ホントならどの程度のバッファを確保するかを考えてからマイコンの選定をするところなのでしょうが、 今回は既にtiny2313を選択肢に仮定しているので、それで大丈夫かどうかを考えてみます。

tiny2313のSRAMは128バイト。 一部はサブルーチンコールのスタックに使われるのでバッファに使用できるのはせいぜい100バイト前後でしょう。

31250bpsと38400bpsで比を取ると出力速度が入力に対して20%近く遅いということになります。バッファを100バイト確保するとしたら、 100バイト÷20%=約500バイト以上のデータが一気にドバッと流れ込んで来た場合バッファを食いつぶす恐れが生じます。

データの内容によって2バイトと3バイトがあると思いますが、ノートオン、ノートオフは1データあたり3バイトなのでこれを基準に考えると 約0.16秒間に166個程度のノートオン+ノートオフが流れ込むとバッファを食いつぶす恐れが生じるということです。 (500バイト×10ビット÷31250bps=0.16秒、 500バイト÷3バイト=166個)

さて、0.16秒に166個の音符がある曲って…それってホントに音楽なのでしょうか? 複数パートが混在する曲であっても、実際はデータとデータの間には間隔があきます。その間にバッファは掃けるでしょうし、 掃ける程度のデータ密度でなければそもそもMIDIの31250bpsという仕様自体が遅延が目立ちすぎて音楽として成り立たないでしょう。

ただ、SMFファイルをPCから再生する場合等には、曲の開始前にシステムメッセージや音色設定などの信号が一気に流れる可能性があります。 曲によってはこのデータが大量かもしれません。その場合はバッファを食いつぶす恐れが無いわけではありません。

100バイト程度のバッファなら、多分瞬間的にこの程度は許容でき、曲がスタートすれば遅延もほぼ無く送受信が出来るものと思われます。 というわけで、このくらいのバッファを取っておけば多分問題ないと判断することにします。(心配な人は適宜フロー制御も組み込んでください)

纏めると、MIDI-IN→PCはバッファリング不要、PC→MIDI-OUTは100バイト程度のバッファを設ければ大丈夫そう、 ってことでしょう。

回路構成

PCとの接続についてはシンプルに。電気的にはごく普通のRS232CレベルならOKなので、大人しくMAX232互換のICを使います。 今回は道具箱からADM232Aを使ってみました。

MIDI側の接続は機器を壊さないようにちゃんと考えつつ、一応部品代もアタマの片隅に置いて考えることにします。

まずMIDI出力。

MIDIはカレントループで接続することになっていて、およそ5mAの電流を流してあげればいいことになってます。

5mAならバッファICを使わずともAVRの出力ピンで直接ドライブできます。なのでAVRの出力ピンと電流制限抵抗で構成することにします。

次、MIDI入力。

MIDIの入力回路は、受けた電流でフォトカプラをドライブすることになってます。 ところがMIDIの通信速度となると1個単価20円前後の安価なフォトカプラでは追従できなくなったり充分な出力電圧変動が得られなかったりするため、 通常は高速なデジタル出力タイプのものが必要になります。

一方pcm1723さんの実験のページ によるとNPNトランジスタでカレントミラーを組むことで安価なフォトカプラでも使うことができ、 しかも結構安定動作するらしいので、有り難くこれを応用させていただくことにします。

というわけで組んだ回路がこれ。(クリックで別窓に開きます)

入出力周りはおよそ一般的な回路になっていると思うので、仮にMIDI-OUTとMIDI-OUT同士を間違えて繋いでも壊れることは無いと思います。 まぁ、pcm1723さんの真似をしたところを除くと大した回路じゃ有りません。

補足。LEDですが、pcm1723さんと同じ理由でLEDに電圧降下の負担をさせているだけです。赤いLEDを1個使いました。 あと、フォトカプラには秋月で5個100円で買い置きしておいたTLP621 を使いましたが、在庫切れのようです(2009.10時点)。PC817C などピン配置が同じものなら多分どれを使っても大丈夫でしょう。

実際に組んで動かしてみて、波形をオシロで拾ったら、pcm1723さんのページにあるような少しだけ角が丸まってるけど奇麗な波形が見れました

あと補足するとしたらDIN5ピンのMIDI信号の配置。おいらはコネクタのピン配置図を見るときに、それがオス側なのかメス側なのか、 そしてそれは表から見た配置なのかハンダ面から見た配置なのかでいつも迷うので、 出来る限り写真にピンを書き込んで残しておくようにしてます。こうすれば実際に配線する時になっても迷い様がないので…。

そうそう、右側のtiny2313のクロック源は左側のtiny2313のクロック出力機能を使うことにします。これによってセラロックを1個省けます。 なので、左のtiny2313は書き込みの際にPD2をクロック出力とするようにfuseを設定します。セラロックをもう1個増やしても構いませんが。

プログラム

tiny2313が2つあるので、プログラムも2個あります。右クリックしてダウンロードしてください。

まずPC→MIDI変換(右側)用の方について。入力はハードウェアUSARTを使います。 入力したデータは、内蔵のSRAMの100バイトをリングバッファに充てて一旦格納しておきます。 バッファに溜められたデータは、1バイトずつ読み出してからソフトウェアのポーリングで1ビットずつ出力していきます。

ただし、出力より入力のピッチが若干速いので、入力データが連続すると1バイト出力している間に次のデータが届くことになります。 出力処理中にもきちんと読み込みとバッファリングを行わないと、すぐにハードウェアUSARTがバッファオーバーフローします。 とういことで、1ビット出力するたびにUSARTにデータが届いているかどうかチェックし、データが来てたらバッファに放り込みます。

ソフトウェアのポーリングはnop命令などを使って出力時間を1クロック単位で管理しているので、 USARTにデータが届いているかどうかのチェックにも神経を使います。特に分岐処理の周りがメンドウ…。 この辺はシミュレーターでフルパスを通してクロック計算すればok。 ちなみにデータ部分8ビット分の出力中はUSART入力有無チェックを行ってますが、スタートビット、ストップビットの出力中はサボってます。 入出力の速度差が小さいので、この程度のサボりならストックとフローの点で特に問題は生じません。

MIDI→PC変換(左側)用の方は簡単。入力より出力の方が早いので入力データをそのまま1ビット単位でポーリングしているだけです。

例によってアクの強いコーディングですが、一度アセンブルが通れば多分修正を行わない類のプログラムだし、 1クロック単位で正確なタイミングを確保することを最優先にしたってことで、まぁいいことにします。

使い方

つなぎ方とか

こんな風に接続して使います。

PCに各MIDIメーカー製のシリアルMIDIドライバをインストールした上で、 PCのシリアルポートに今回の製作物をストレートケーブルで接続すると、MIDI-INが1個、 MIDI-OUTが1個のMIDI入出力端子として機能します。

ちなみにオンボードのシリアル端子ではなくUSB-シリアル変換コネクタを介すると、市販のUSB-MIDI変換ケーブルと同等になるんですが、 その件は下記に。

このように、シリアルMIDIドライバを通すことでwindows上のアプリからは極普通のMIDI機器として見えるように成ってくれるので、 市販のシーケンサソフトだろうとwindows mediaplayerだろうと、自作プログラムだろうと、何でも接続することが可能です。

しかも、普通のシリアルi/fとしても扱うことが出来るので、MIDIとのやり取りを自由自在に読み書きすることも出来るわけです。超便利!

使い方

普通のMIDI変換ケーブル類と一緒です。例えば外部音源に接続しておいて、SMFファイルをwindows mediaplayerとかにドラッグドロップすれば鳴るし、 キーボードとかのMIDI楽器を繋げば、シーケンサーだろうとソフトウェアシンセだろうと、MIDIの演奏にしたがって音を拾ってくれます。

データの中身には特にタッチしてないので、ノートオン、ノートオフとかだけじゃなく、音色の変更とかも普通に機能します。

USB経由にしたい…

さて注意を要するのは先ほどのUSB経由の接続の場合。USBシリアル変換ケーブル類を使う際の各社シリアルMIDIドライバとの相性のこと。

幾つかの組合せで実験してみたところ、動く組合せと動かない組み合わせが存在するようです。実験結果をまとめておきます。 といっても、動くか動かないかを保証するものではありません。私の環境での結果です。時と場合と環境によって異なる恐れが強いです。

ドライバ\変換ケーブルATEN製UC-232A秋月製AE-UM232R
ヤマハ製(com1~com4)動かず(com4)動かず(com4)
ローランド製(com1~com4)設定できず(com4)動いた(com2)
カワイ製(com1~com2)動いた(com2)動いた(com2)

というわけでcom2が空いているなら、カワイのドライバを使ってシリアル変換コネクタ(かボード)をcom2に割り当てて使うのが良さそうです。

ローランド製の「設定できず」の件はブログに書き残してあります。

もちろん、オンボードシリアル(com1)が自由自在に使えるなら動作的には一番安定して使えます。USBじゃないけど。

便利な使い方

やはり何と言ってもUSB接続にしてしまいかつ電源もUSBから取ったら、市販のUSB-シリアル変換ケーブルと同等になっちゃって便利。

秋月のAE-UM232RはFTDI社のFT232-RLチップを登載したUSB-シリアル変換ボードです。これなら電源もここから取れるし、 今回使ったADM232AをFT232-RLに置き換えてしまえばばっちり。市販のUSB-MIDI変換ケーブルと同じ機能と利便性を持ちつつ、 しかもシリアル端子経由で通信内容をモニターできちゃったり…。

あとでPCBEでも使ってFT232-RLを登載する専用ボードでも描いてみたいなぁ。プログラムは使いまわせるし…

追記:FT232RLでUSB接続

やっぱ世の中はUSB。

シリアルポート接続だと最近のノートPCなどでは繋げられないし、電源も別途用意する必要があって不便なので、 FT232RLをつかって通信も電源もUSBケーブル1本で済まそうという作戦を考えてみました。

回路図

MAX232互換ICの代わりにFT232RLを使ってみました。これなら電源もUSBから取るので、通信と電源がUSBケーブル1本でok。

電源周りはフェライトビーズとパスコンでノイズ対策としました。それ以外は特に凝ったことはしてません。

USB化するなら、よく考えたら最初からUSB内蔵のPIC18F2550やPIC18F14K50あたりを使えばIC1個だけで作れちゃうんじゃないかなぁ、 とかいう話は気付かなかったことにします。ホント言うと、MIDIから入力してモニター表示できればいいやってところからスタートしてるから… tiny2313を1個だけで用が足りるはずだったんだけど、無計画に機能追加しちゃったからな…

工作

万能基板とタカチのケースを使って纏めてみました。FT232RLは0.65mmピッチで扱い難いので、変換基板を使ってます。

動作確認

作り上げたモノを幾つかの観点でテストしてみます。プログラムレベルでは既に機能確認が済んでいるんだけど、 組み合わせてみてちゃんと動くのかと言う点(設計面)と、組み立ててみてちゃんと動くのかという点(製造面)の、主に2つの観点です。

ワンオフだから、特に製造面の不安が大きいわけですね。

1:USB接続のMIDIインターフェース互換機能

パッケージ全体としてはUSB接続のMIDI入出力端子そのものなので、 MIDIマスターキーボードを繋いでPC側のソフトウェアMIDI音源を鳴らすことができるのかとか、 windowsのMIDI出力をこの基板を通して出力して、外部MIDI音源がちゃんとなるのか、とか確認します。

まずはMIDIマスターキーボードを繋いでソフトウェアMIDI音源を鳴らしてみると→ok、ok。問題なし。

次。メディアプレイヤーでMIDIファイルを再生したり、MIDI演奏対応のゲーム(ネクタリスのwindows用フリー版: 以前はハドソンで無料ダウンロードできたんですが、公開を止めてしまったみたい…残念)を暫く動かしてみて、 特に不具合は生じませんでした。

とりあえず、USB-MIDI変換器としての機能は普通に動いているようです。ヨカッタ、ヨカッタ。

2:シリアルMIDIモニター用の接続端子として

この間VB2005で作ったアレと組み合わせてMIDI機器からの信号を表示したり、 MIDI音源へ信号を出力したりすることに問題が起きないか確認します。

特に、FT232RLと.net環境(VB2005含む)はなんとなく相性が良く無さそうなので…

まず外部音源に繋いでみて、モニタープログラム画面上の鍵盤を弾いて見ます→ok、ok。遅延も特に無く音が鳴ってくれます。

次。MIDIマスターキーボードを繋いで、信号をモニター画面で拾います→弾いてから画面に現れるまで時間が掛かってしまう…。(1~2秒)

以前ハマッたとおり、 FT232RLドライバのレイテンシ設定が16m秒のままでした。イカン、イカン。

レイテンシを1m秒に変更して再度確認→うーん、やっぱり上手く行きません。レイテンシを色んな数値に変えてみたり、 バッファサイズを弄ってみたり、いろいろ変えてみたんだけど上手く行かず…何故だろう???

暫く色んなケースを設定してテストしてみるも、上手く行かず…

同じようにシリアル通信としてデータを受信するんでも、tera-termなら遅延無く受信できるんだよなぁ…(バイナリだから文字化けはするけど)

結果

ブレッドボード使って同じ FT232RLチップ登載の秋月製変換ボードで実験した時には上手く動くことが確認出来たんだけど、 チップもドライバも同じなのに上手く動いてくれないのは何故…???

ちなみに通信が遅れることはあっても、欠落することは無いみたい。でもその遅延が何故起きるのか、どうやったら解消するのかはわからず仕舞い。 うーん、とりあえず.net環境とFT232RL(というかシリアルインターフェース全般)の相性が良くないってことみたいだなぁ。

同じチップ、同じドライバを使って相性が出たり出なかったりするのは釈然としないんだけど、オイラのチカラではここまで。 まぁ、USB-MIDI変換ケーブルとしての機能自体は確認出来たので、あとはPC側ソフトを.net以外で作れば問題ないってことなんだろうな。

メンドウなのでそれを作るのはまた今度ってことにして、とりあえず.net環境で動くソフトじゃなければそれなりに動くってことは確認できました。

とりあえず当面はこのまま放置として、そのうち気が向いたら.net以外の環境で動くソフトを作ってみたいところです。

この状態で一旦凍結としたい…な。なにか進展したらまた更新します。