USBキーボードが接続できたので、マウスも接続できるんじゃない?ということで、マウスの接続に挑戦してみた記録です。
1. PC-88VAのマウスプロトコル解析
PC-88VA側のマウスI/Fですが、BNNのPC-88VAテクニカルマニュアルによると、X/Yの移動量データを4ビット単位に以下の順で送信すると書いてあります。
-
X上位4ビット
-
X下位4ビット
-
Y上位4ビット
-
Y下位4ビット
え?待って、これ、普通に違和感ありますよね?
この時代のNEC(MSXマウス仕様だとしても)は、Z80 or Intel8086系の互換CPUしか使っていないんだから、「上位→下位」は違うんじゃない?と思いますよね?
そもそもテクニカルマニュアルって、誤記多過ぎるし、どうせまたこれも誤記なんだろう
・・・と思っていた時期が私にもありました。
実際にオシロで見てみたら、書いてある通りでした。
ちなみにストローブ波形はこんな感じでした。
-
約16.7ms周期
-
ON 約100μs
-
OFF 約66.7μs
-
ON 約66.7μs
-
OFF
16.7msってあたり、垂直帰線割込みに同期しているのでしょうね。
そのあたりは納得できます。
しかし、もう1つ、納得できない話があります。
それは転送される4ビットデータの形式です。
最初は「ビット反転」だと思っていたのですが、実際には、「正論理のまま符号反転」でした。
つまり、
+1 → -1
-1 → +1
のような感じ。
いや、これ、明らかにビット反転と符号反転の違いを理解できていない人が設計してるよね?
FM音源のI/Oとか8255とか使ってるから、ビット反転で入力したいというのなら理解できるけど、何故に符号反転?全く意味が解りません。
でも実際、調べてみるとそうなっているんだから仕方がない。
当時のNECの新人社員に仕様作らせて、ノーチェックで出荷しただろ?と疑ってしまうようなお粗末な仕様で、正直、驚きました。
(MSXマウスとかもそうなの?知ってる人、情報求ム!)
2. Timer2割込み処理追加
最初はメインループ内でストローブを監視していました。
まあ、ループしちゃうと普通にWatch Dog Timerでリセットされてしまうので、WDOGリセットをかけながらループするんですけどね。
でもやっぱり、USB処理やキーボード処理も同時に走っているのに、ストローブ監視の為に他の処理を止めてしまうのは、下策でした。
あちこちで処理落ちするようになってしまいました。
結局、Timer2割込みを使って20μs周期でストローブ監視する方式に変更。
「割込み処理をどこまで重くしていいのか?」
というのは、はっきり言ってわかりません。
まあ、とりあえず今は動いているからヨシとしています。
3. USBマウスのプロトコル仕様
USBマウスのプロトコル仕様(Boot Mouseと呼ぶらしい)は、以下の通りです。
-
ボタン → 8ビット ビット列 (各ビットがボタンに対応)
-
X移動量 → 符号付き8ビット数(-127~+127)
-
Y移動量 → 符号付き8ビット数(-127~+127)
-
ホイール移動量 → 符号付き8ビット数(-127~+127) (オプション)
ホイールがあれば4バイト。なければ3バイト。解り易くてたいへんよろしい。
しかし、これはあくまでも「基本的には」という話。
キーボードと同様に、Bootモードだったらそうです、みたいな話のようです。
私の手元にあった複数のUSBマウスを繋いでみると、ほとんどが移動量は16ビット。
上記、Boot Mouseプロトコルでそのまま動いたのは、中華製ノーブランドマウスのみでした。
とりあえず、動かないマウスには、
SET_PROTOCOL(BOOT)
という、デバイスにブートモードを指示するUSBホストコマンドがあるので、これを送ってみました。
結果は、移動量が8ビットになるマウスもあれば、完全無視するマウスもある、ということに。
うーん、微妙・・・
まあ、BIOS設定画面はだいたいキーボード操作なので、困っていないのでしょうね。
結局、受信パケット長が4バイト以下なら正規のBoot Mouse仕様、それ以上なら移動量16ビット仕様と見なすようにしました。今のところ、手元にある4台のマウスはそれで動いています。
4. USBマウスの移動量積算
最初、USBパケットから取り出したマウスの移動量を、X/Yそれぞれの変数領域に毎回上書きしていました。
多少ロストしても、マウスなんて人が手で動かしているんだからいいでしょ?
ぐらいに思っていたのですが、やっぱりそれではダメだったようです。
PC-88VA側は16.7ms周期なので、その間に来たUSBパケットが失われて、マウスの動きが妙に遅くなってしまいます。
そこで、
USB側の移動量を積算 → PC-88VAのストローブタイミングで放出
という方式に変更。
動きは自然(というか普通)になりました。
USBマウスから送られてくる移動量はだいたい±10以下ぐらいが多いようなので、16ビットには拡張せず、積算値は8ビット符号付きで保持し、±127でクリップしています。
PC-88VAの解像度ならこれで十分そうです。
5. HUB対応?
今回の変換器は、かんたんUSBホスト (HIDキーボード用)をベースに使っています。
元々USB HUBに対応しており、複数のキーボードを同時に接続することができるようになっています。(キーボードを複数接続したいシチュエーションがよくわかりませんが…)
当然ながら、マウスも複数台同時に接続できるようにするべきでしょう。
・・・と思ったが、ん~、ダメだこりゃ
やっぱりちょっと処理が重くなってきているようです。
マウスを激しく動かしていると、Hub Port Disableが発生して、HUBの接続が解除されているようです。
ここでUSBの仕様を読んでみると・・・
あれ?
USB仕様を読むと、通信パケットロスト時にHubがPortをDisableにするのは正しい動作ですが、その時のホスト側の対処方法は、
- Disableをクリア
- ダメならポートリセット
- それでもダメなら接続解除
(ただし、接続解除まで、必ず4ms以上は待つこと。)
となっています。
つまり、HUBの動作が仕様と違う。これはどうしましょうかね?
HUBを作るのは今回の趣旨ではないんだよね~。
他にも小さなバグは数箇所見つけているんだけど、これは作者に報告すべきか…
まあ、PC-88VAにUSBマウスを2台接続したい人なんていないから、問題ない。
と、今はそうしておきます。
6. まとめ
とりあえず、
-
USB有線マウス (バッファローマウス、X68000Zマウス、中華製ノーブランドマウス)
-
USB無線マウス (ロジテックマウス)
-
HUB経由
-
キーボード同時使用
あたりは動作確認できました。
ソフトはそれなりに動くようになったという認識です。
なので、ソフト開発の方はこのぐらいにしておいて、冒頭の写真の通り、現状、まだブレッドボード状態なので、次は基板化のほうを進めていこうと思います。
