じょんのブログ

じょんのブログ

NEC PC-88VA2を修理(?)している記録です。

PC-88VA用キーボード・マウス変換器ですが、ソフトの方もだいたい完成したので、ブレッドボードだったインタフェース部分を基板に作り替えました。


私は元々ソフト屋さんで、ハード制作が得意なわけでも何でもないので、写真は遠目にしておきます。

黒井電気さんのかんたんUSBホストはそのまま使っています。

本当はブレッドボードに差していた足を上向きにしてインタフェース基板を上に載せるような感じにしたかったのですが、足のピンをどうしても上手く外すことができなかったので、USBコネクタが上に出っ張ったような形になっています。

かんたんUSBホストをもう1台買えたら良かったのですが…再販してくれないかな。


で、足のピンを頑張って外そうとしていた時に、基板上の回路を破損してしまい、LEDが点灯しなくなってしまいました。

3.3VからLEDにつながる線を切ってしまったようだったので、今はジャンパー線で接続しています。

写真が遠目なのはそんな恥ずかしい状態だったからなんですね。


さて、インタフェースボードは完成しましたが、ケースに入れるかどうかは未定です。

というかケースに収める前提で作っていないので色々と厳しいかな?

気が向いたら3Dプリンタで専用ケースを作るかも?

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にするのは正しい動作ですが、その時のホスト側の対処方法は、

  1. Disableをクリア
  2. ダメならポートリセット
  3. それでもダメなら接続解除
    (ただし、接続解除まで、必ず4ms以上は待つこと。)

となっています。

つまり、HUBの動作が仕様と違う。これはどうしましょうかね?

HUBを作るのは今回の趣旨ではないんだよね~。

他にも小さなバグは数箇所見つけているんだけど、これは作者に報告すべきか…

 

まあ、PC-88VAにUSBマウスを2台接続したい人なんていないから、問題ない。

と、今はそうしておきます。

6. まとめ

とりあえず、

  • USB有線マウス (バッファローマウス、X68000Zマウス、中華製ノーブランドマウス)

  • USB無線マウス (ロジテックマウス)

  • HUB経由

  • キーボード同時使用

あたりは動作確認できました。

ソフトはそれなりに動くようになったという認識です。

なので、ソフト開発の方はこのぐらいにしておいて、冒頭の写真の通り、現状、まだブレッドボード状態なので、次は基板化のほうを進めていこうと思います。

 

↓この続きです。

 

 

PC-88VA用USBキーボード変換器のお話の続きです。

動作確認では、ずっと安物のキーボードを使っていましたが、HUB経由で複数のキーボードを接続する試験のために、ちょっと高級(?)な別のキーボードを接続してみたところ、正常に動作してくれないことが判明しました。

 

接続時のログを調べてみたところ、このキーボードは、以下のように、1つのUSBデバイス内に2つのInterfaceを持っているようです。

  • Interface 0
    HID Boot Keyboard (class=3, subclass=1, protocol=1)

  • Interface 1
    N-Keyロールオーバー キーボード + Consumer Control
    Report ID付き

元々のUSBホストの実装は、

  • 1デバイス = 1キーボード

を前提に処理していたため、同一USBデバイス内に存在する複数のインターフェイスを別々のキーボードと認識して、キーボードオブジェクトを2つ作ってしまい、USBメッセージを奪い合っていたようです。

AIとお話して分かったのですが、このキーボードが特殊というわけではなく、そもそもUSB HIDデバイスでは

  • 1つの物理USBデバイス

  • 複数の論理入力デバイス

という構成が普通に存在するらしいですね。

 

以前に書いた記事で、USBキーボードは一定の時間間隔で、以下の8バイトのデータを垂れ流してくる、と書きました。

ofs. val.
0 modifier
1 reserved
2 usageID 0
3 usageID 1
:
7 usageID 5

これは概ねウソではないのですが、すべてのキーボードが常に上記のプロトコルで動作しているわけではありません。

高級なゲーミングキーボード等では、たくさんのキーの同時押しを正しく処理するために、OS起動後は別のプロトコルに切り替えることがある、ということなのだそうです。

ただし、そういったゲーミングキーボードでも、BIOSブート等の為に上記のプロトコルもサポートする必要があるので、高級なキーボードほど、1つの物理USBデバイスに複数の論理入力デバイスという構成になりがちなのだそうです。

 

上記の表に書いた古典的なプロトコルをBoot Keyboardとか、BIOS Keyboard等と言ったりすようです。

デバイスのインターフェイスディスクリプタの内容で判別可能なので、class=3, subclass=1, protocol=1であることをチェックするように修正し、Boot Keyboard Interface のみ処理するようにしたところ、問題なく動作するようになりました。

 

なかなか奥が深いですね。