2014年6月14日土曜日

続・ChromeにおけるWeb MIDI APIの実装状況

昨年末にWeb MIDIの実装状況について書かせて頂きました。その後の更新状況についてまとめたいと思います。

Chrome 34
  • Linuxサポート(ALSAをサポートするシステムのみ)
  • Androidは出力のみ対応(ただし、初期化手順の問題で最初の呼び出しは失敗する)
  • リアルタイムメッセージのサポート
  • システムメッセージ(sysexではない)はパーミッションなしで送信できるように修正
  • 送信メッセージにエラーがある場合、詳細情報がエラーメッセージとして書き出されるようになった
  • パーミッション許可を求めるinfobarが file://... に対しても表示されるようになった。ただし、セキュリティの都合上、許可・不許可は記憶されない。
  • Windowsでtimestampが間違っていたのが修正された
Chrome 35
  • PromiseがWeb MIDI向けの機能限定版から、フル機能版に差し替えられた
  • Chrome OSサポート
  • Androidの入力サポート(初期化手順の問題は未修正)
  • OS Xにおいて送信されるMIDIメッセージにCore MIDIのtimestampが正しく付加されておらず、Chromeから送信されるデータをDAWで受信すると、正しいタイミングで録音できない問題が修正された
  • MIDIAccess.sysexEnabledアトリビュートが追加された
Chrome 36
  • Androidの初期化手順の問題が修正された
Chrome 37(予定)
  • LinuxとChrome OS向けの実装が改善された(ALSA sequencer APIに対応)
  • Android向けのUI実装完了(infobarと設定画面)
追記:Chromeで実装しているAPIは最新版と若干異なります。最新の使用に合わせて近々更新する見通しですが、それまではこちらの旧APIを参照願います。またMIDIConnectionEventの実装も新APIになるまで見合わせています。

For English readers;
I'd summarize Web MIDI implementation status on Chrome. I also did it at the end of the last year, but in Japanese. So, I'd mention also previous status together.

Chrome 30
  • chrome://flags#enablr-web-midi appeared on OS X
  • Input ports were available on OS X, but there was a bug on sysex until Chrome 32
Chrome 31
  • Output ports were also available on OS X
  • Infobar and settings UI were implemented as a part of content settings
Chrome 32
  • IAC driver was available
Chrome 33
  • Web MIDI worked on Windows, but had wrong timestamp values
Chrome 34
  • Web MIDI worked on Linux (but only ALSA supporting systems)
  • Also, worked on Android, but only output ports are available
  • There was a problem on initialization process, so the first API call didn't work on Android
  • Real-time messages were available from this version
  • System messages were available without a sysex permission from this version (previous versions required a sysex permission even for system messages)
  • Error provided detailed messages on invalid send messages
  • Infobar appeared even on local files, but browser could not remember the permission because of security reason
  • Wrong timestamp was fixed on Windows
Chrome 35
  • Now, Promise is not limited version Promise, MIDIAccessPromise, but fully featured proper Promise
  • Now the API is available on Chrome OS
  • Input ports are available on Android, but the initialization issue is not fixed yet
  • Fix a bug that sending messages had wrong CoreMIDI timestamp and caused a problem that DAW could not record Chrome sending messages with correct timestamp
  • MIDIAccess.sysexEnabled attribute is added
Chrome 36
  • Android initialization issue will be fixed
Chrome 37 (planned)
  • Linux and Chrome OS supports will be improved so to support ALSA sequencer API
  • Infobar and settings UI for Android will be implemented
Note: The implemented API is slightly different from the latest W3C spec. You can see the old specification here. Also, MIDIConnectionEvent is not implemented yet. It will be available once new API is ready.

2014年2月20日木曜日

SDCC for PIC Tips

PIC18F14K50でUSBデバイスを作るのにSDCCを使ってみた。PIC18F2550系とは互換性がないという事前情報だったけど、レジスタ並びやUSB用RAMのアドレスが違うくらいで、基本的にUSB周りのコードはほぼそのまま動きそう。

むしろハマったのはSDCC周辺。このあたり、やっぱり非公式ツールチェインは辛い。大きくハマったのは次の2点。

  1. bootloaderを使おうとすると色々細工が必要で、信頼できるコードが書けない
  2. USB用RAMのポインタをアドレスから普通に作ると動かない
bootloaderについて、まずtext領域を後ろ(0x800以降)にずらすために専用のリンカスクリプトを用意する必要がある。コンパイラオプションにもそれっぽい--code-locというのがあるが、指定しても動かなかった。また、割り込みベクタはbootloader側がトラップして後ろのアドレスにフォワードしてくれるので、後ろのずれた位置に割り込みベクタを配置する必要がある。こっちはコンパイラオプション--ivt-loc=0x800が正しく動く。また、crtが通常の配置を想定したコード(割り込み周りかな?)を持っているようで、ふとしたタイミングで暴走する。stdio/stdlib使ってなくても、例えばcharをやめてintでforループを回すと暴走、とか悩ましい問題が普通に起きる。海外サイトでcrtを同じフラグでコンパイルし直せば安定する、という話も見かけたけど、どこまで信じていいかわからない状態で実験を続けたくなかったので、bootloaderは諦めた。回路側でバランスをとったら、なんとかICSP指しっぱなしで書き込みしつつ、USBバスも安定ドライブできた。

USB用RAMについてはコンパイラの問題とは思わずに長時間悩んだ。いわゆるBuffer Descriptor Tableを構成するコード。コンパイラの仕様が変わったのか、バグなのか、2550の時のコードからアドレス変えただけでは動かなかった。具体的にはstruct bd* bdt = (struct bd*)0x0200;的な事をやってアドレスを作ってたんだけど、今回はこのポインタで読み書きしても値が変わっていなかった。起動すれば一応USBはしゃべるんだけど。アドレスリセットとパワーセーブ関連の割り込みだけ届いて、その後はだんまり。トランザクションが届かないってことはエンドポイントが正しく初期化できてないのかなぁ・・・というあたりから問題の目星をつけた。結局コンパイル結果を眺めながらの間違い探し。原因が判明してからは、正しい出力を出せそうな表記を勘を頼りに探すお仕事。通らないと承知で間違ったキャストをコンパイラにかけると、内部的な秘密の型がエラーメッセージを通して推測できるのでオススメ。
__at(0x0200) struct bd BD0;static struct bd __near* const bdt = &BD0;
あと、やっぱり配列でアクセスしたくなるUEP0, UEP1, ...なんかもchar *uep = (char*)&UEP0; uep[0] = ...とか書くと正しくアクセスできない。
static __sfr* uep = &UEP0;static __UEP0bits_t* uepbits = &UEP0bits;uep[0] = 0;uepbits[0].EPHSHK = 1;
って感じの__sfr*という特殊な指定が必要。特定用途レジスタの略だと思う。こっちはシステムヘッダを眺めて予想。

2014年2月3日月曜日

HIDじゃないSPX

とりあえず手元のAKI-PICで焼けるPIC18F2550で作ったpic18spx(オリジナルそのまま版)と、それを使ってPIC18F14K50に焼いて作った非HID化改造版pic18spx。
非HID化によりOS Xでも動くようになりました。あと、次にbuildしようとした時にbuildできる環境が作れる気がしないのでhexをウェブ上に置きました。必要になったらここからダウンロードして焼くべし>未来の自分。

あと、昔tcl/tkで書いたhidspx用のGUIが昔の記事にあります。開発中はもっぱらmakeを叩くんだけど、デバイスを確認する時とか、FUSEの値を確認する時、今でも使ってます。

しかし、環境乗り換えの時間的コストは高いな、やっぱり。

2014年2月2日日曜日

pic18spx/mac

HIDクラスを使ってるとOS Xで標準ドライバから制御が奪えない問題。HIDをやめれば解決するかな、と思って試したら解決した。具体的にはUSBデスクリプタのインタフェースクラスをHIDからベンダ固有値0xffに変えるだけ。picmonとか特に修正しなくても、そのまま利用できる。

むしろpic18spxのファームのbuild環境を整えるのに苦戦した。mcc18向けに書かれてるんだけど、現在はmcc18は配布されておらずMPLABXとXC8が標準。いっそXC8かSDCCに移植しようかと思ったけど、そこまで時間かけても仕方ないかな、と思って大昔のディスクを漁ってmcc18をインストール。持ってたのはMPLAB-C18-Academic-v3_30.exeとかいう古めのバージョンだったので、そのままではリンクできない。とりあえず$(TARGET).cofのビルドルールを以下のように変えて凌いだ。

$(LD) /l$(MCC18)/lib /k$(MCC18)/lkr rm$(DEVICE).lkr $(OBJS) \
/u_CRUNTIME /z__MPLAB_BUILD=1 /m$(TARGET).map /o$(TARGET).cof

とりあえず、自分のファーム作るときは最初からSDCC考えた方が良さそうだなぁ・・・。

2014年1月29日水曜日

18F2550 -> 18F14K50

本日14K50が届いたので準備の続き。先日ブレッドボードで組んだpic18spxはリセットボタンを付けて基板に載せました。部品点数少なすぎて基板がスカスカ。配線ガシャガシャしててもUSB側は安定してるんでリセットボタンいらなかったかも。書き込み用のピンは手元の機材ですぐに実験できるAVR用の2×3タイプのみ。

右が2550。TINY2313の読み出しを確認した後、左の14K50を使った2台目の書き込みに。書き込みにはpic18spx-2010-0416に付属のpicwriter.exeを利用。hidspxでいけるもんだと思い込んでて-rが成功せずにしばらく悩んだ。

新たにブレッドボードで動作確認。リセットをプルアップしてる以外はクロックと配線のみの超手抜き状態。ですが、安定動作してます。水晶は秋月で28.6円のSG531PAP。水晶のOUTをCLKINに繋げてCLKOUTは開放。設定変更くらい必要かと思ったけど、そのままで動いてる。こっちは基板では2×3と1×6両方付けるつもり。
と、ここまででようやく開発の準備が完了です。
そう言えば、フルスピードになると我が家のオシロでは対応できないので、ハード側でハマると死にそうです。

2014年1月26日日曜日

pic18spx

手持ちのPICライター、AKI-PICではPIC18F14K50に書き込めないっぽいので対策。嬉しい事にさくっと見つけたpic18spxが需要を満たしてくれそう。個人的に嬉しいポイントは

  • Linux / OS Xからも使える
  • PIC18F2550とPIC18F14K50に対応してる
  • ライターもツールもhidspxの上位互換として動く(AVRにも書き込める)
  • PIC18F2550と20MHz水晶だけで作れるので、手持ち在庫とAKI-PICで作れる
ってところ。

回路

ざっくりオフィシャル通りでこんな感じ。
追記:RC2をpull upしてるけど標準hexではBoot Loaderは殺されてるので不要

Linux / OS Xでの利用(ややハマりポイントあり)

picmon/picbootは関してはオフィシャルページのpic18spx-2010-0416.zipを展開すればWindows用のバイナリと一緒にソースが入ってる。picspxは別途配布されているpic18spx-linux.zipを使うこと。
Linuxでは中で呼んでるusb_claim_interface()にroot権限が必要なため、sudoしないと駄目。オフィシャルページ読めば書いてあるけど見落としてた。hidspxではroot権限不要だったと思うんだけど・・・まじめに調べてないけど、単純にhidspxはcontrol転送しか使ってないんで標準HIDドライバが不審に思って掴まなかっただけな気がする。
同じ理由でOS Xでもusb_claim_interface()が失敗。こっちはrootでも駄目。usb_detach_kernel_driver_np()を試しても失敗するのでusb_strerror()を読んでみたら「function not implemented」を返してきた。もう少し検索してみるとこんなスレッド発見。要は標準ドライバ避けに専用kernel driver作ってOSを再起動するしか方法はないらしい。まぁHIDはセキュリティ的にも際どいし、わからなくもない。
よくよく考えるとWindows使わない身としてはHIDのフリをさせるメリットもないので、独自クラスにデスクリプタ書き換えたfirmwareを作ることで解決するつもり。そうしとけば、その気になればUSB API使ってChromeからも書き込めるし。

そのほかハマった点

前エントリの通り、最新版のAKI-PICを試そうとして危うくVM上のWin XPを再起不能にしかけた。しかも試し損。加えてVMのUSBブリッジが不安定。結局、唯一稼働してる実機Windows、Win7/LOOX U50WNを引っ張りだしてPIC18F2550を焼いた。ライターにhidspxを使ってPICに書けるPICspxなんてのあったけど、うちの環境で読み込んでみたら不定値が返ってくる。ライター側のバージョンでAPIが微妙に変わってそうなので、深入りせずに過去に実績のあるAKI-PICに逃げた。これがAKI-PIC最後の出番かも。
追記:USBブリッジの問題はホスト側で/etc/udev/rules.d/40-vmware.rulesみたいなのを以下の内容で作ってやったら解決した。USBデバイスのパーミッションが常に全開放になる点だけは注意。vmware server 2.0/Ubuntu 10.04.4 LTSの組み合わせ(この組み合わせもいい加減古い)。
SUBSYSTEM=="usb", ENV=="usb_device", MODE="0666"
SUBSYSTEM=="usb_device", MODE="0666"

関係ないけど驚いたこと

vimでhexファイル(PICのa.out的なもの)を開いたらレコードごとに色分けして表示してくれた。超便利。これ見ながらpicmonで期待してるデータが読めるか確認。ピンクが長さ、青がアドレス、赤がタイプ、無印がデータ、最後の黄色バックがチェックサムです。

2014年1月25日土曜日

AKIPIC PICPGM6β6.76でハマった

最新版のデバイス対応状況を確認しようとしてカジュアルにアップデートかけたらOSが起動しなくなった。一番悪いのは僕。なにせ使ってたのはXP、アハハ。

問題は単純で、システムのOLEAUT32.DLLを上書きされちゃう。Vista以降でしか動かないバージョンで。エラーメッセージ的にはMSVCRT.DLLにstrcat_sのエントリが見つからない、といってexplorerも何も動かなくなっちゃうんだけど、実際にはエントリがないのがXP版としては正しくて。Vista以降のMSVCRT.DLLに依存を持ったOLEAUT32.DLLがインストールされたのが本質的な原因。

ってことで、対処としては、OSのインストールディスクをドライブXに用意して、コマンドプロンプトを使って以下の処理を行う。explorerは起動しないけど、Ctl+Alt+Delからタスクマネージャは呼べるので、ファイル>新しいタスクの実行(N)…からcmd.exeを実行です。
C:¥WINDOWS¥system32>ren oleaut32.dll oleaut32.bak
C:¥WINDOWS¥system32>x:
X:¥>cd i386
X:¥I386>expand oleaut32.dl_ c:¥windows¥system32
X:¥I386>c:
C:¥WINDOWS¥system32>ren oleaut32.dl_ oleaut32.dll
更新履歴にはVista以降はまだ準対応とか書きながら、実際はVista以降でしか動かないという…かなり攻撃力高いです。っていうか、僕悪く無いじゃん、やっぱり。