ここ - ectoyfan のページ

2015-05-23(土) PSoC まつり 2015 資料
ブログ「王様の耳はロバの耳!」http://blog.goo.ne.jp/ectoyfan 掲載記事より
PSoC5LP で USBMIDI
ectoyfan
難しい工作をしないでなるべくお手軽楽チンに PSoC5LP で遊ぼうというお話です.
今回の PSoC まつりでいちばんゆる~いプレゼンをめざします.
用語 MIDI(Music Instrument Digital Interface)[1,2] 電子楽器の演奏データを機器間
でデジタル転送するための世界共通規格.USBMIDI[3] USB 上で MIDI データをや
り取りするための規格.
使った機材 (1) USB 接続口のついた PSoC5LP 基板 圓山宗智さんが設計された
PSoC5LP 基板[4](MPSOC5-MB,書籍に付属,税抜 3,800 円)を使います.いま日
本で一番安定して手に入れられる PSoC5LP 基板のひとつだと思います.プログラマ
も同一基板上に載っていて楽チンです.(2) 液晶ディスプレイ 演奏の状況を確認す
る手段がないとやはりきついので,ここでは MARY-OB 基板[5](MARMEX-OB,マ
ルツエレック,税抜 3,315 円)を用いて,演奏状況をモニタリングすることにします.
(3) AF アンプ+スピーカ PSoC5LP 自体にスピーカを駆動する馬力はないので用意
します.わたしは電池で動くスピーカつきアンプ(TK-735R,イーケイジャパン,税
抜 1,900 円)を使っています.(4) その他 母艦として圓山さんが設計された PSB 拡
張基板[6](MPSOC5-SB,マルツエレック,税抜 14,096 円)を使っています.MARY
基板のソケットを1つ持っていること,ステレオ出力可能のオーディオ出力を備えて
いることなど,こまごましたことを全部任せることができてこれまたとても楽チンで
す.
USBMIDI を利用するプログラムのひな型 USBMIDI モジュールの説明はマニュア
ル[7]の 45~53 ページにありますが,これだけ読んですんなりプログラムが書ける人
はあまりいないんじゃないかと思います.いろいろ試して,たぶんこういうことだろ
うというのが,プログラム1です.MIDI シーケンサーソフトなどから発せられた
MIDI メッセージを受け取るための骨格はたったこれだけです.あとは必要なデータ
だけを選別して処理すればいいわけです.
コールバック関数の実現 プログラム2はコールバック関数の実現の例です.MIDI
のチャンネル 10 はデフォルトでドラムパートに用いられるので,既存の MIDI デー
タを修正せずに演奏できるよう最初から除外しています.ピッチベンドに対応する場
合は,ピッチベンドデータに加えて,ピッチベンドセンシティビティのデータを合わ
せて受け取る必要があるため,コントロールチェンジデータの処理が必要になります.
音源の実現 もとはといえば,AY-3-8910 や SN76489 などの PSG(Programmable
Sound Generator)を PSoC3/5LP につないで鳴った鳴ったと喜んでいるうちに,楽譜
情報を打ち込むのが面倒→MIDI データ使えばいいじゃん,という流れなので,最初
は PSG を音源に使おうと考えたのですが,1個の PSG あたり 3 音ですから,まとも
void USBMIDI_1_callbackLocalMidiEvent(uint8 cable, uint8 *midiMsg) {
// USBMIDI_1_MIDI_OUT_EP_Service() のコールバック関数
// midiMsg に 3 バイトデータがやってくる
// システムエクスクルーシブについては
// 先頭バイトが 0xf0 である 3 バイトデータから
// 0xf7 を含む 3 バイトデータまでがひとまとまり
// (0xf7 以降は無視)
}
int main() {
…
CyGlobalIntEnable; // グローバル割込み許可
…
USBMIDI_1_Start(0, USBMIDI_1_3V_OPERATION); // USBMIDI 初期化
while (!USBMIDI_1_GetConfiguration()); // USB が準備できるまで待つ
USBMIDI_1_MIDI_EP_Init(); // MIDI メッセージ送受信の準備
…
for (;;) {
…
USBMIDI_1_MIDI_IN_Service(); // ホスト(PC)に MIDI メッセージを送信
USBMIDI_1_MIDI_OUT_EP_Service(); // ホストからの MIDI メッセージがあればコールバック関数を呼ぶ
…
}
…
}
プログラム1:USBMIDI を利用するプログラムのひな型
// USBMIDI_1_MIDI_OUT_EP_Service() のコールバック関数
int skip_flag = 0; // システムエクスクルーシブメッセージを読み飛ばし中
void USBMIDI_1_callbackLocalMidiEvent(uint8 cable, uint8 *midiMsg) {
if (skip_flag) {
if (midiMsg[0] == 0xf7 || midiMsg[1] == 0xf7 || midiMsg[2] == 0xf7) { skip_flag = 0; }
} else {
if (((midiMsg[0] & 0xf0) == 0x80 || (midiMsg[0] & 0xf0) == 0x90)
&& (midiMsg[0] & 0x0f) != 0x09) { // Note on & off でかつドラムチャンネル(10ch)でない
if (!Q_isFull()) { Q_EnQ(v_NODE_NOTEONOFF(midiMsg[0] & 0x0f, midiMsg[1], midiMsg[2])); }
}
if ((midiMsg[0] & 0xf0) == 0xb0) { // コントロールチェンジ
if (!Q_isFull()) { Q_EnQ(v_NODE_CONTROLCHANGE(midiMsg[0] & 0x0f, midiMsg[1], midiMsg[2])); }
}
if ((midiMsg[0] & 0xf0) == 0xe0) { // ピッチベンド
if (!Q_isFull()) { Q_EnQ(v_NODE_PITCHBEND(midiMsg[0] & 0x0f, midiMsg[1], midiMsg[2])); }
}
if (midiMsg[0] == 0xf0) { skip_flag = 1; } // システムエクスクーシブメッセージ
if (skip_flag && (midiMsg[1] == 0xf7 || midiMsg[2] == 0xf7)) { skip_flag = 0; } // 短いシステムエクスクルーシブメッセ
ージの処理
}
}
プログラム2:コールバック関数の実現
な演奏のためには何個 PSG をつながないといけないの?,とあっさりめげて(笑)
,
PSoC5LP の内部に音源を作ることにしました.最初は図1のように PWM をずらっ
と並べて,それぞれの PWM モジュールの出力をいったんステータスレジスタに受け
て,それぞれのチャンネルのボリューム分だけ加えて足し合わせるという作戦をとり
ました.(この CPU では 9 個まで PWM モジュールを取ることができるみたいでし
たが,きりがいいので8個になっています.)これでうまくいったので喜んでいたの
ですが,実際にいろいろな MIDI の音楽データを再生してみると,音数がまるで足り
ません.それに PSoC5LP という CPU の性能からいえば,音が 8 個しか使えないと
いうのはいかにも情けない気がします.さてどうしたものか…
図1:音源の実現(ファーストトライ)
一晩悩んで,結局完成版は図2のようになりました.32bit のタイマーが1個,ず
っと動いています.この値を,鳴らしたい周波数の 1/2 周期に相当するカウント値
で割り算します.その答えが奇数なら H,偶数なら L とでも決めてやれば,PWM
でやっていたのと同じデータが得られる…これで一気に音数をふやすことができま
した.32 音で作ってみましたがまったく問題なく動きます.
図2:音源の実現(改良版)
ピン配置ならびに配線のようすを図3に示します.DAC の出力を P3[7]に出して,
PSB 基板の AOUT0,1 につなげば配線は完了.MARY-OB 基板は PSB 基板のソケッ
トに挿せばあとはピン設定だけです.
図3:ピン配置ならびに配線のようす
図4はクロック設定です.CQ の PSoC5LP 基板は水晶つきですのでそのように設
定しています.USB を使う場合は,ILO=100kHz, IMO=24MHz, USB=IMO×2
=48MHz と設定するように指示されています.
図5は MIDI シーケンサー(Domino 1.43)から実際に演奏をさせているところです.
方形波しか使っていないわりにはけっこう聞けます.90 年代の MIDI 華やかななり
しころ,Niftyserve 等のパソコン通信では,愛好者の作った MIDI データが盛んにや
りとりされていて,完成度の高いものが多くありました.そんなデータをひっぱりだ
してきてごそごそ聞いていると,夜が更けるのも忘れてしまいます.いかん,明日仕
事にならないぞ…そうそう,NSX-39[8]と組み合わせると一気に現代の楽しみかたに
なって楽しさ倍増です.
図4:クロック設定
図5:演奏のようす
今後の課題 音源情報を取り込むこと,とくにドラムパートを演奏できること,せめ
てエクスプレッションには対応すること,などが課題かな…そうそう,PSoC3 でもや
ってみたのですが,いまのやり方では CPU パワーがまったく足りない(8 音で 6kHz
サンプリングが精一杯)ので,何かよい方法を考えたいです.ちなみに,新発売の
PSoC5LP Prototyping Kit (CY8CKIT-059)では問題なく動作しました.
参考文献
[1] JIS X 6054-1:1999 “電子楽器デジタルインタフェース(MIDI)― 第 1 部:総則”,日本工業規格,1999-0120.
[2] JIS X 6054-2:1999 “電子楽器デジタルインタフェース(MIDI)― 第 2 部:プロトコル仕様”,日本工業規格,
1999-01-20.
[3] USB Implementers Forum: Universal Serial Bus Device Class Definition for MIDI Devices, Release 1.0,
1999-11-01.
[4] 圓山宗智: 基板付き体験版 ARM PSoC で作る My スペシャル・マイコン, トライアルシリーズ,CQ 出版社,
2013-12-01.
[5] 圓山宗智: 2 枚入り!組み合わせ自在!超小型 ARM マイコン基板,トライアルシリーズ,CQ 出版社,201104-01.
[6] 圓山宗智: 開発編 ARM PSoC で作る My スペシャル・マイコン, トライアルシリーズ,CQ 出版社,201401-01.
[7] Cypress Semiconductor Corp.: Full Speed USB (USBFS), Version 2.80, PSoC Creator Component Datasheet,
2014-12-17.
[8] 大人の科学マガジン編集部(編): 歌うキーボード ポケット・ミク,学研教育出版,2014-04-03.