1. このプロジェクトは

近頃話題の nanoKEY、私も入手しました。nanoKEY、小さくて便利ですが、USB MIDI のみ対応なので、USB ホストがないと使えません。

普段のシンセ作業では、nanoKEY 導入以前から、PC から MIDI モニタソフト経由で MIDI 信号を出していたので、USB MIDI でも全く不都合ないのですが、nanoKEY をたとえばデモなどで持ち出して使いたいときには、PC がなくてはいけなくて少しとりまわしが悪いです。

ということで、nanoKEY をスタンダロン MIDI 化すると、とっても便利そうです。このプロジェクトは、「nanoKEY を持ち運びできるポータブルキーボードにする」ことを目的にします。

2. アプローチ

nanoKEY を持ち運びできるようにするには、二通りの方法が考えられます。

  1. nanoKEY を改造してレガシー MIDI が出せるようにする
  2. 邪魔にならないぐらい小さな USB-MIDI ホストを作る

さっさと作りたいので、なるべく既存のものを利用した「アホな」方法でやります。nanoKEY の改造は、とりあえず今回は置いておいて、小さなホストを作ることにします。ホストももう実装しない。手持ちにシングル・ボード・コンピュータがあるので、以下のような構成でやってしまいます。

nanoKEY -> (USB) -> シングル・ボード・コンピュータ (Linux) -> (シリアルポート) -> MIDI out

「持ち運びしても小さい」は、シングル・ボード・コンピュータの小ささで実現。ずるいですが。

USB の受け口は、既存の Linux の USB-MIDI ドライバを使うことにします。

SBC -> シリアルポート の部分だけは、後々の改良も考えて、自分で組むことにします。

3. まずはデスクトップPCで nanoKEY を動かしてみる

いきなり SBC を使って動かなかったとき、切り分けが大変すぎるので、まずはデスクトップ PC を使って動かしてみます。Debian をインストール(あとでバージョンを記入)、さらに、kmidimon をインストール、nanoKEY からの信号を認識することを確認。kmidimon は、ALSA (Advanced Linux Sound Architecture) の sequencer API を利用しているようです。ということで、USB-MIDI -> シリアル MIDI のリダイレクタは同じ ALSA sequencer API を利用して組むことに決定。

4. ALSA sequencer API とは

The ALSA sequencer interface is designed to deliver the MIDI-like events between clients/ports.

だそうです。イベントの形でメッセージを処理できる MIDI ドライバだと思っとけばいい、というのが現時点での理解です。(あってんのかい?)

どうも、ドライバとアプリは同列のオブジェクトとして設計されているようです。おのおのポートを立ててポート経由でイベントの受け渡しをします。感覚はソケットにかなり近いです。イベントの待ちも poll() 関数でやるらしい。ただし、低レベルの入出力関数は使いません (read() とか write() とか)。

そうすると、これからやればいいことは

  1. USB-MIDI ドライバのポートを探してつなぐ
  2. Serial MIDI ドライバのポートを探してつなぐ
  3. イベントハンドラを書く(USB->シリアルにリダイレクトするだけ)

やり方さえわかれば難しくはなさそうです。

5. nanoKEY から Serial MIDI へ接続

(2009.04.05追記)

まずは、aconnect コマンドを使って nanoKEY から Serial MIDI へ接続します。aconnect  -i コマンドで出てくる ‘MPU-401 UART’ は、シリアルポートの MIDI とはまた別であることがわかりました。シリアルポートを MIDI インタフェースとして使うには、別途 Serial MIDI が使えるようにする必要があることがわかりました。やり方は、以下のページが参考になりました。
http://www.geocities.jp/midi_organ_net/alsa/

Serial MIDI を登録して、aconnect コマンドで nanoKEY と Serial MIDI を接続。オシロスコープでシリアルポート出力の TxD 端子を監視、MIDI データが送られてくることを確認しました。ここまでは良い感じです。

遅延などのパフォーマンスは未確認ですが、遅延が問題なければリダイレクタのプログラミングもいらない気がしてきました。

ワークログは以下のとおり:

$ su -
# setserial /dev/ttyS0 uart none
# setserial /dev/ttyS0
/dev/ttyS0, UART: unknown, Port: 0x03f8, IRQ: 4
# /sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4
# exit
logout
$ aconnect -i
client 0: 'System' [type=kernel]
    0 'Timer           '
    1 'Announce        '
client 14: 'Midi Through' [type=kernel]
    0 'Midi Through Port-0'
client 20: 'MPU-401 UART' [type=kernel]
    0 'MPU-401 UART MIDI'
client 24: 'nanoKEY' [type=kernel]
    0 'nanoKEY MIDI 1  '
client 28: 'Serial MIDI (UART16550A)' [type=kernel]
    0 'Serial MIDI 1   '
$ aconnect -o
client 14: 'Midi Through' [type=kernel]
    0 'Midi Through Port-0'
client 20: 'MPU-401 UART' [type=kernel]
    0 'MPU-401 UART MIDI'
client 24: 'nanoKEY' [type=kernel]
    0 'nanoKEY MIDI 1  '
client 28: 'Serial MIDI (UART16550A)' [type=kernel]
    0 'Serial MIDI 1   '
client 128: 'KMidimon' [type=user]
    0 'input           '
$ aconnect 24:0 28:0
$ aconnect -i --list
client 0: 'System' [type=kernel]
    0 'Timer           '
    1 'Announce        '
        Connecting To: 15:0, 128:0
client 14: 'Midi Through' [type=kernel]
    0 'Midi Through Port-0'
client 20: 'MPU-401 UART' [type=kernel]
    0 'MPU-401 UART MIDI'
        Connecting To: 128:0
        Connected From: 24:0
client 24: 'nanoKEY' [type=kernel]
    0 'nanoKEY MIDI 1  '
        Connecting To: 20:0, 128:0, 28:0
client 28: 'Serial MIDI (UART16550A)' [type=kernel]
    0 'Serial MIDI 1   '
        Connected From: 24:0
$

6. USB MIDI をレガシー MIDI に変換

(2009.10.05追記)
その後、シリアル MIDI は、実は普通の MIDI と、ボーレートが違うことがわかり、作業がとまっていました。これを手っ取り早く解決するには、USB -> レガシー MIDI の変換装置があればよいのですが、しばらく放置になってしまいました。そろそろやらなくちゃっと、重い腰をあげて、作りました。

もあさんの Pepper を土台に使わせていただきました。

回路図はこちら。usb-midi-bridge-schematic

ファームウェアは、もあさんの Pepper-MIDI の USB レシーバ部を使わせていただいて、そこにソフトウェアシリアルを実装して実現しました。めにーさんくす to もあさんなのであります。

ファームウェアはこちら

以下は、Windows プラットフォームを介して、Nanokey を動かしているところです。

7. ホストPCをセットアップ

(2009.10.21追記)

ホストPCは、なるべく小型にしたかったので、Single Board Computer を使うことを予定していました。

ところが、手持ちの SBC が不安定だったため、急遽ハイテックシステム社Micro PCに切り替えました。サーバ機として運用していたので、安定性には問題ありません。

7.1 ホストPCの概要と OS の選定

このPCは、コンパクトフラッシュを IDE ディスクとして使えるので、起動ディスクには 1GB のコンパクトフラッシュを使いました。

OS には、Puppy Linux を使いました。これは、CD など固定メディアから起動できる Linux で、以下の点で今回のプロジェクトにとても向いています。

  • OSイメージを RAM ディスクにロードして動作可能なので、CF のような、書き込み寿命があるメディアにやさしい。
  • しかも、システムに変更をかけたら、シャットダウン時に差分をメディアに記録してくれる。
  • OS イメージを RAM ディスクにロードしちゃうので、シャットダウンプロセスを介さずいきなり「電源ばっちん」で落とせる。つまりキーボードもディスプレイもなくても運用可能。

7.2 OSのインストール

CF へのインストールは、Puppy Linux を CD ブートしてから、Puppy Universal Installer というツールを使って行います。この作業は、Puppy Linux のページにある説明どおりにやればOKです。起動オプションとして、 「OS を RAM メモリに完全ロードする」 (copy) を設定しました。

7.3 OSの設定

ALSA は幸いはじめからインストールされているので、aconnect がそのまま使えます。PCにはディスプレイもキーボードもつけないので、勝手に立ち上がって、勝手に nanoKEY と変換ブリッジをパイプしないといけません。それようの perl スクリプトを書きました。

スクリプトはこちら

スクリプト中にある “nanoKEY” というのが、nanoKEY の識別名です。変換ブリッジは “USB-MIDIBRG” です。 このスクリプトはPCの稼動中ずっと走り続けないといけないので、起動時に呼び出されるようにします。

スクリプトを /usr/local/bin/auto_aconnect に置いて、/etc/init.d/alsa ファイルを以下のように編集して、start スクリプトの末尾で auto_aconnect が呼ばれるようにします。

$ diff -u alsa.org alsa
--- alsa.org    2009-10-21 01:43:22.000000000 +0900
+++ alsa        2009-10-21 01:43:36.000000000 +0900
@@ -51,7 +51,6 @@
     alsactl -f /etc/asound.state restore #from /etc/asound.state.
    fi
   fi
+  /usr/local/bin/auto_aconnect &
  ;;
  stop)
   alsactl -f /etc/asound.state store #saves to /etc/asound.state.

7.4 どんな風に使うか

このシステムは、電源を入れると起動します。起動完了すると、auto_aconnect が走り出しますので、nanoKEY と変換ブリッジが USB ポートに刺さっていれば、自動的にパイプしてくれます。

以上で、接続完了。簡単ですね。途中の抜き差しも可能です。

終了にはシャットダウンは必要ありません。電源を「ばっちん」と落として完了です。

9 Comments

  1. pcm1723

    ALSA が入っているのであれば、コマンドラインで

    aconnect

    とすれば、スピードなどはともかく、機能としてはポートどうしをつなぐことができるはずです。

  2. pcm1723

    前のコメントで、引数部分が消えていました。
    正しくは、

    aconnect 入力ポート 出力ポート

    です。

  3. ワイファイ用のホストマシンが2千円ぐらいで(LANポートとか、色々付いて)帰るんだそうです。穴あいてて、テルネットできるとか。
    そのアプローチ、ありかもですー。

  4. Gan

    pcm1723 さん:
    アドバイスありがとうございます。nanoKEY をつないだ状態で

    % aconnect -i
    client 0: 'System' [type=kernel]
        0 'Timer           '
        1 'Announce        '
    client 14: 'Midi Through' [type=kernel]
        0 'Midi Through Port-0'
    client 20: 'MPU-401 UART' [type=kernel]
        0 'MPU-401 UART MIDI'
    client 24: 'nanoKEY' [type=kernel]
        0 'nanoKEY MIDI 1  '
    

    まだシリアルからのデータをモニタできませんが、24 から 20 につなぐ、ということでうまく行きそうな気がします。

    takeda さん:
    SBC は1万円ではきかないので、これだけのために買うのはばかばかしいですけれども、2千円ならいい感じですね。シリアルポートがついていれば完璧。ただ、CPUは絶対に386互換じゃないと思うので、コンパイルとか苦労しそうです

  5. 確かに、SBCを使うという手もありますね。ソフト環境が揃っているので、構築は比較的楽に出来そうですね。
    USBホスト内蔵ワンチッップやARMを使ったアプローチはフリーのUSB HOSTプロトコルスタックの入手がキーになりそうです。

  6. Gan

    もあさんの ARM 実装方式楽しみにしてます。
    私は、手抜きアプローチで :-)

  7. ARMはフリーのプロトコルスタックがないので、AVRが良さそうです。
    といっても、まだプロジェクトは開始していません。

  8. もう動いたのですね。素晴らしい。
    LinuxのSBDを使うアプローチですが、BeagleBoardだと小型で非常に良さそうです。http://beagleboard.org/
    今月出荷の始まったRev. C基板だとちゃんとUSB HOSTも動作するようですので、同じ手続きで動作させられそうです。

  9. Gan

    BeagleBoard 良いですね。価格的にもサイズ的にも魅力です。
    今回は COM ポートを使うことを前提に考えているので、そこが一番難しそうなところと思われます。近頃では、SBC でもシリアルがつかなかったりするのですね。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください