<前の記事 : 次の記事>
今回もニッチなPIC16F1454でUSB-MIDI変換
なんかとち狂ってUSB-MIDI変換器でも作ってみようかなwとかやってみたらすごい大変だった。とりあえず動作させたオレ様素晴らしい。手持ちで立派な製品も持っているのに!
元にしたのはやっぱりMLAなんだが、これが例としては微妙すぎた。PC/macからMIDI インタフェースとして認識されるのは素晴らしいのだが、USB側からのMIDIパケットは無視、リセットボタンを普通のボタンとして使用し、押すと適当なNoteOnを出すというものだった。シリアル送受信とか自分で考えろってことなのか。いいのかそんなんで。Arduinoなんてライブラリ一発だぞ(そこそこ準備が必要だけどw)。
Copilotに振り回される
PythonスクリプトなどはCopilotに書かせても一発で動いたりするが、学習が足りないのかPICはダメだ。例えば、「PIC16F1454のRX/TXはRB4/RB5だぞ間違えんな修正しろ」って自覚のない嘘を言ってくる。「データシート読んだのかボケぇ、そもそもPORTBすらないだろフザケンナ」とか言えば「よくわかってんなお前」とか上から目線でしれっと訂正しながらほめ殺しだ。おっかなくてそのままコピペなんて出来やしない。
ちょっと複雑な処理を「なんか動かないんで見てくれや」って聞くと「バッファ0にステータスを収納すんな、データだけにしろ、そうしないとバイト列がずれちゃうよん」とか一見まともな意見を出すんだが、やっぱり動かない。そう指摘すると「あなたのコードはここが間違ってる」って言ってくる。
間違ってんのはお前のコードだろ。
まずは周辺を整える
Windowsからmacに乗り換えたので、ちょっと設定関連がわからないことが多い。昔から音楽とか映像ならmacだろとか言われてきた割には支援が薄い感じがするんだよな…(知らんだけかも)
GarageBandとか機能がすごいのは認めるが、使い勝手が直感から離れすぎている、と感じる。そしてAudio MIDI設定ではmacに接続したキーボードをうまくルーティングできない。いかにもルーティングしまっせ!という画面なんだがうまくいかない。なんでかなw
PCでMIDI関連のチェックをする時に以前からPocket MIDIを使ってたんだが、macでも使えて大変助かった。ありがとう。ただし、invalidのモニタができずに表示されないため、これだけではデバッグには向かない。同時にMIDI Monitorを起動しておくとエラーでもinvalidとして表示されて役に立った。ありがとうございます。
あとシリアル変換結果のモニタとしてターミナルが必要だが、いつも使っててバイナリ表示もしやすいSerial Monsterでボーレート31250の設定方法がわからなかった。その代わりCool Termが設定画面で31250を手打ちでき、バイナリでも表示できるので、MIDIモニタとしてはこれが良かった。結局、入力はPocket MIDI、出力はPocket MIDI/MIDI Monitor併用でMIDIキーボードの出番は無かった。
しかしmac OSのフリーウェアへの風当たりって酷すぎないかw
MLA流用内容を整える
MLAはソースが分散されてプロジェクトの流用が面倒なので、まずは一旦使われている全てのヘッダーとソースファイルを、あらかじめ作っておいた空のプロジェクトフォルダにコピーした。
忘れずにsystem.hにあるUSE_INTERNAL_OSCを有効化し(コメント外し)ておく。指示通りパスコンを大容量(1〜8μF)にしておかないと動作しないらしいが、最低の1μFでも大丈夫そうだ。ちなみに低価格の電解コンデンサセットの実際の容量はかなり怪しい(もしくはハズレを掴まされる可能性がある)。
USB処理のメインルーチンはポーリングになっていて割り込みは使っていないが、割り込み関数が定義はされてしまっているので、シリアル関連で割り込みを使うためには削除する必要がある。
書き込んで動作確認をしてみると、USBから送ったMIDIパケットは完全無視、リセットボタンを押す度に適当なNoteOn/Offが出ることがわかる。
シリアル変換を整える前に
USBからやってくるMIDIパケットは64バイト固定の受信バッファーに以下の4バイト構造で1ms毎にやってくるらしい。
typedef union {
uint32_t Val;
uint8_t v[4];
union {
struct {
uint8_t CIN :4;
uint8_t CN :4;
uint8_t MIDI_0;
uint8_t MIDI_1;
uint8_t MIDI_2;
};
struct {
uint8_t CodeIndexNumber :4;
uint8_t CableNumber :4;
uint8_t DATA_0;
uint8_t DATA_1;
uint8_t DATA_2;
};
};
} USB_AUDIO_MIDI_EVENT_PACKET, *P_USB_AUDIO_MIDI_EVENT_PACKET;
structの最初のバイトは4ビットずつに分割されているが、パケットサイズは4バイト固定で最大64バイト(=16パケット)が1msでやってくると約512kbpsの通信速度になる。一方でシリアル側は31.25kbpsだから16倍以上の速度差がある。つまり送信待ちをリングバッファで構成するなら、このサイズは最大化する必要があると言うことだ。逆に受信データを貯める方はUSBにすぐ引っこ抜いてもらうのでかなり少なくてもなんとかなりそうだ。なくてもいいかもしれない。
USB側もバッファを設けることを考えると、今度は送られてくるデータ(PICから見ると受信)に速度制限はない(=大バッファ必要)が、送るデータはちまちま送られてくるシリアルデータなのでバッファは小さくていい。
この記事はここまでにして次の記事で実際の実装を考えていく。
投稿者の人気記事

-
akira.kei
さんが
前の日曜日の16:30
に
編集
をしました。
(メッセージ: 初版)
-
akira.kei
さんが
昨日の0:50
に
編集
をしました。
-
akira.kei
さんが
昨日の0:54
に
編集
をしました。
-
akira.kei
さんが
昨日の15:14
に
編集
をしました。
ログインしてコメントを投稿する