お知らせ:この記事はJLCPCBの提供でお送りしています。

みなさんこんにちは。今回は前後編に分けて、8bitUSBマイコン・CH554を使ったUSB-MIDIホストの製作記を紹介したいと思います。前編では制作のきっかけとプロトタイプの作成過程について書いていきます。

CH55xでもっと遊んでみよう

今回取り上げる、USBホスト・デバイス機能を搭載した8bitマイコンのCH554ですが、実は一度#makepcba 第2回で製作した自作マクロパッドの記事で紹介しています。この記事内ではCH55xduino環境を使い、CH554をUSBキーボードに仕立て上げていました。また、当時はキースイッチ以外の部品をJLCPCBのPCBAサービスで実装してもらっていたのですが、PCBAのオーダーを出す前に、お試しでJLCPCB Parts LibraryのMy Parts Lib機能を使って先行でCH554を10個確保していました。マクロパッドのPCBAは5枚しか製造していなかったため、私が持っている(ことになっている)CH554はまだ5個残っている状態でした。なので、どこかで使わなければ…と考えていました。

秋田先生の新刊「CH55xでどうでしょう」

そうこうしているうちに、2022年の終わりにニコ技深圳コミュニティ分解のススメも一緒に書きました!)でご一緒している金沢大学の秋田先生が「CH55xでどうでしょう」という新刊を出されるということを知りました。

そこで、これはこの波に乗って在庫のCH554を使いきってしまうのがいいのでは?と思い、CH554を使ったUSB-MIDIホストを作ることにしたのでした。なお、上のツイートの通り、発売後「CH55xでどうでしょう」はしっかり読ませていただきました。ミニマルなので若干癖のあるCH55xの周辺回路を理解するうえでかなり役に立ちました!

なんでUSB-MIDIホスト?

さて、今回作るUSB-MIDIホストというのは、接続されたUSB-MIDIデバイスと、通常のMIDI(レガシーMIDI)のデバイスの信号を相互に変換して送受信するUSB機器になります。

なぜ数あるUSBモノの電子工作の中から、USB-MIDIホストを選んだのかというと、

  • せっかくなのでCH554の持つUSBホスト機能を使いたかったから
  • そもそも自分が必要としているから
  • たぶんCH554でできるだろうという見通しがあったから

…というのが大きな理由です。

まず最初の「せっかくなのでCH554の持つUSBホスト機能を使いたかったから」ですが、読んで字のごとく、USBデバイスだけでなくUSBホスト機能も持っているというのがCH554の特徴なので、これを生かしたものを作ってみたかったということです。以前作ったマクロパッドはUSBデバイスなので、ホスト機能非対応のCH552でも実装できたのですが、たまたまJLCPCB Parts Libraryで品切れだったのでCH554を代替品として手に入れていたのでした。

次の「そもそも自分が必要としているから」というのは、これまでいくつか紹介しているように(最近だとPCM音源の自作記事も書きましたね)、MIDI音源をいくつか作っていて、これを駆動するための環境にUSB-MIDI機器を組み入れたいということです。

私が作るMIDI音源はレガシーMIDIにしか対応していないので、PCからMIDIデータを送る場合はUSB-MIDIインターフェースを別途使い、USB-MIDIからレガシーMIDI信号を変換して送り込んでいます。自宅で楽しむ分はそれだけでもいいのですが、昨年のNT金沢への出展時のように、展示しているMIDI音源をその場で演奏してもらおうとするとキーボードが欲しくなります。

レガシーMIDIの付いたコンパクトな市販のキーボード(ヤマハのCBX-K1などなど…)は生産終了になってから久しく、一方でUSB-MIDIにのみ対応したキーボードはKORGのmicroKEY2など、さまざまな現行機種が入手可能です。これらのUSB-MIDIキーボードを展示会場で使おうとすると、一番素直な方法ではUSB-MIDIキーボードとUSB-MIDIインターフェースをそれぞれPCにつなぎ、PCを仲介してキーボードの入力を音源に入力する構成となります。PCからMIDIデータを送り込んだりもできるため、柔軟性があってこれはこれで便利な時もありますが、展示の時にはちょっと機材が多くなってしまい不便です。

この手の悩みはMIDI音源を自作する人だけではなく、USB-MIDI普及前のレガシーMIDIのみ対応の古い音源やシンセサイザーを使う人も持っているため、いくつかのメーカーからUSB-MIDIホスト機能を持った製品が発売されています。

私も写真のDOREMiDiのUSB-MIDIホストを持っていて、NT金沢での出展時などに使っていました。ただ、ケースがかなりしっかりしたつくりで、電源もUSB Type Bコネクタで入力、MIDIのIN/OUTも最近流行りのTRS(3.5mmミニジャック)タイプではなく、昔ながらのDINタイプです。そんなわけで、もう少しコンパクトなUSB-MIDIホストを作れないかな…と思っていました。

最後に「たぶんCH554でできるだろうという見通しがあったから」という点ですが、上の写真のUSB-MIDIホストを分解してみたところ、中身の基板上に実装されているICは(MIDI用のフォトカプラ等を除いて)1個だけでした。

画像

IC表面の表記こそリマークされたような形跡がありCH554かどうか判別はつかないですが、パターンを追いかけた感じだと、ICのピン配置がCH554Tと合致しそうだということが分かりました。今までのところファームウェアの読み出し等は成功していないのでCH554だという確証はないのですが、これを見てどうやらCH554のようなワンチップマイコンでもUSB-MIDIホストを実装できそうだな、と感じたのでした。

まずはCH559評価ボードで実装開始

作るものが決まったところで、まずはプログラムを実装するぞと思い、たまたま持っていたCH559の評価ボードを引っ張り出してきました。CH559はCH554の上位機種で、動作周波数が速かったりRAM容量が大きかったりします。

環境構築はLang-shipさんの記事「USBホストになれるCH559入門 その1 開発環境構築」を参考に行いました。私もコンパイラのSDCCだけは最新の4.2.0を別途ダウンロードしてインストールしました。

Lang-shipさんの記事中で紹介されているCH559sdccUSBHostにはメーカー公式のUSBホスト用サンプルコードをSDCCで動くように修正したサンプルが同梱されています。私もこれを下敷きに実装を始めました。

詳しい解説は専門書に譲ります1が、USBホストとデバイスが通信する場合、デバイスの種類を問わず、USBホスト側からデバイスにリセットをかけ、その後ホストがデバイスからディスクリプタと呼ばれるデバイスの素性を表した情報を順次読み込んでデバイスの認識と初期設定を行うという流れになります。今回のサンプルコードはUSB HID2を認識してデバイスの状態を読み取るというものでしたが、この初期化とディスクリプタの読み込みの部分は流用できそうだったので、まずはサンプルコードに手を加えて、USB-MIDIデバイス3を判別して認識できるようにするところまで実装しました。

ディスクリプタの読み出しの部分はすでにあるものが活用できるので、ディスクリプタの中身からUSB-MIDIデバイスを判別する部分をUSB-MIDIの仕様書を読みながら実装しました。

USB-MIDIデバイスの判別処理を実装した後は、USB-MIDIデバイスからのデータを受け取れるようにさらにサンプルコードを改造していきました。といっても、HIDで使われるUSBのデータ転送モードの一つであるインタラプト転送と、USB-MIDIで使われるバルク転送は処理としてはほぼ一緒なので、ここも割とすんなり実装することができました。

意外と手間だったCH554への移植

そうこうしている間に、AliExpressでオーダーしていたCH554の評価ボードが届きました。(写真では基板からワイヤーが生えていますが、これは私が改造した跡です。)

早速CH559で書いていたプログラムをCH554に移植するぞ、と作業を始めたのですが、思いのほかCH559とCH554の間には差分があることに気が付きました。今回ハマったところを中心に差分をまとめると以下の表のようになります。

項目 CH559 CH554
RAM容量 256B+6KB 256B+1KB
最大動作周波数 56MHz 24MHz
GPIOの動作モード 7モードから選択+駆動電流2段階 4モードから選択
USB 2系統 1系統

RAM容量やここに記載していないROM容量の差分があるということはある程度想定していましたが、それ以外の周辺回路のレジスタなどは大体共通だろうと思っていました。USBに関してはレジスタのアドレスが異なる程度で済みましたが、クロック回りとGPIO回りは意外と仕様が異なり、CH554の周辺回路はCH559のものからさらに簡略化されています。クロック回りとGPIO回りはLチカなどの基本的な動作確認の時にも関わってくるので最初に移植しなければならず、思いのほか手間がかかりました。ただ、周辺回路はかなりがっつり簡略化されているものの、ユースケースはきちんと押さえられるようになっていて、よく考えられているなあと感心しました。

最初にある程度想定していたと書いたRAM容量についてですが、USB-MIDIホストそのものの機能を実装するには十分なものの、デバッグのためにCH559では普通に使えていたprintf()を使おうとするとRAMが足りなくなりました。USBの通信用にバッファを取る必要があるので、256B+1KBもRAMがあるとはいえ、贅沢はできないなという印象でした。結局、printf()は使わず、自作の1byte数値 to 16進2桁文字列変換関数とputs()を使うようにしたり、USBの通信用のバッファを送受それぞれ64bytesに削るといったことをしてRAMを確保しました。ESP32などのモダンな32bitマイコンのぬるま湯に浸かって久しいので、この手のデバッグ用関数を書くのは久々でした。USBメモリなどのマスストレージクラスデバイスのような、それなりに大きいバッファを用意した方が効率がよい用途にはCH559かよりモダンなUSBマイコンを使う方がよさそうです。

また、コンパイルが通るようになって最初にCH554でプログラムを動かしたときには、UARTでのデバッグプリントは正常に出ているのになぜかUSBデバイスが応答しないという問題に引っかかりました。結局この問題はUSBの通信用バッファのアドレスを正しくレジスタに設定できていなかったことが原因だったのですが、この原因究明の際にロジアナが役立ちました。24MHz8Chの安いロジアナも便利ですが、もう少し速い信号がキャプチャできるロジアナがあると、フルスピード(12Mbps)のデバイスのデバッグにはとても役立つということが分かりました。4

そんなこんなでUSB-MIDIデバイスを認識するプログラムを無事移植できたところで、次に基板の設計とUSB-MIDI/レガシーMIDIの信号の相互変換の部分の実装を行いました。この部分は後編で詳しく説明します。お楽しみに!

参考情報

ここまでの記事中で触れたWebサイトの他に、CH559/554の開発を行う上で参考にしたページを以下に示します。

CH559での開発のハマりどころをかなり細かくまとめてくださっています。

「格安~」のWebサイトでも言及されています。CH554への移植時など、メーカー公式のサンプルソースを直接読んだ際にKeilとSDCCの差分などの情報が役立ちました。

  1. ちょっと古いのですが、月刊Interfaceの2014年12月号の特集が大変よくまとまっていてお勧めです!
  2. Human-Interface Device:マウスやキーボードなどのデバイス
  3. 正確にはUSB Audio ClassのMIDI Streaming Interface Subclassのデバイス
  4. ちなみに私はDSLogic Plusを使っています。
公開日:2023/01/28 最終更新日:2023/01/29