[Japanese|English]

Morphy USB-IO の仕様

I/O ポートのハードウェア

Morphy USB-IO の I/O ポートに他の回路を接続するために必要な情報をまとめました。以下の情報は、Morphy USB-IO の中核である Cypress CY7C63001A のデータシートの情報と、Morphy USB-IO のファームウェアを調べた結果に基づいています。何か間違っているかもしれません。特にタイミングに関する部分は、かなりよくわからないので推定値です。(オシロ持ってないんで、実測できないんです。)

I/O ポートの構成

Morphy USB-IO には 12 ビットの I/O ポートがあります。これは、Port #0 と Port #1 という 2 つのグループに分かれています。Port #0 は 8 ビット、Port #1 は 4 ビットあります。各 I/O ポートは、1 ビット単位で任意に入出力として使うことができますが、Port #0 と Port #1 は対等ではなく、いろいろな違いがあります。

I/O ポートの等価回路

CY7C630001A の I/O ポートは、かなり工夫された回路構成になっていて、それなりに複雑です。また、ファームウェアによる設定で振る舞いを変更できる部分もあります。私は、最初、入力と出力をどうやって選択すればいいかなど、基本的な部分がわからず悩みました。

Morphy USB-IO のファームウェアによる設定を前提として、思い切って単純化すると、図に示すような等価回路になると思えばいいようです。

I/O ポートの等価回路

ポイントは、出力バッファがスリーステートではなく、オープンコレクタとプルアップ抵抗の組合せになっている点です。つまり、I/O ポートには入力と出力の選択という考え方はなく、出力として見ると常に出力レジスタの内容が出力され、入力として見ると常に外部信号と出力レジスタのワイヤード AND が入力されることになります。入力として読み取られるのは出力レジスタの値とのワイヤード AND になりますから、意味のある入力を行うためには、対応出力レジスタは HIGH レベルになっていなければなりません。このことは、入力として使う I/O ポートを駆動する外部回路の出力段がオープンコレクタでない (通常の出力、トーテムポール構成) 場合に、大電流が流れないようにするためにも重要です。(とは言え、CY7C63001A の出力段は、実際には電流制限の機能を持っているため、普通の TTL の出力同士を直結して HIGH と LOW に駆動したときのようなひどいことにはなりません。)

まとめると、I/O ポートの使い方は、以下の通りです。

なお、Morphy USB-IO では、I/O 端子は必ず内部でプルアップされており、ハイインピーダンスにすることはできません。これは、ファームウェアの制約です。(CY7C63001A というチップ自体には、プルアップをはずして、端子をハイインピーダンスにする機能もあります。)

駆動能力

Port #0 のグループと Port #1 のグループは、出力として使うときに駆動できる電流の量が違います。Port #0 は「小出力用」という位置づけになっており、最大でも 1.5mA までしか吸い込むことができません。Port #1 は「大出力用」で、最低でも 8mA 以上流すことが可能です。HIGH レベルのときの流れ出し電流は、どちらのグループも大して取れません。単にプルアップ抵抗を流れる分だけです。このため、LED を駆動するような用途には、Port #1 をアクティブ Low で使うことが推薦されています。

なお、このプルアップ抵抗の値は、Port #0 と Port #1 に共通に、定格上 8 〜 24kオームという大雑把な規定になっているようです。

ファームウェアのバージョン

モルフィー企画が販売する (販売した) USB-IO に搭載されているファームウェアには、2種類のバージョンが存在するようです。これは ver.1 と ver.2 で、現在頒布されているものは ver.2 になっているようです。

なお、ファームウェアのバージョンはプリント板のバージョンとは異なります。現在販売されているプリント板は、ver. 4 になっているようです。

USB デバイスとしての構成

デバイスの構成

Morphy USB-IO は、PC 側からは、HID クラスに属す低速 USB デバイスとして扱われます。HID ですが、マウスやジョイスティックなどの標準のデバイスではないため、大抵の OS では「その他の HID デバイス」のような扱いになるはずです。Windows 98 では「HID 互換デバイス」のように呼ばれます。

USB デバイスとして見ると、Morphy USB-IO は、1 つのコンフィグレーション、1 つのインターフェース、2 つのエンドポイントを提供する単純な構成です。エンドポイントとして、デフォルトコントロールパイプを構成するエンドポイント0と、HID デバイスに必須のインタラプトパイプを構成するエンドポイント1を持っています。

リクエスト

Morphy USB-IO は、デフォルトコントロールパイプを通して、以下のリクエストを受け付けます。

ディスクリプタ

Morphy USB-IO が返すことのできるディスクリプタは以下の通りです。

ソフトウェアインターフェース

USB-IOとの通信方法

Morphy USB-IOはHIDデバイスです。しかし、HIDデバイスのフリをしているだけで、実際の振舞いは、普通のHIDデバイスとは大分違います。

Morphy USB-IOとの通信は、「コマンド」と「応答」という2種類の通信によって行われます。コマンドは、ホスト (PC) からUSB-IOに向けて送られる8バイトのデータで、SET REPORT リクエストのペイロードとして送られます。応答は、USB-IOからホストに向けて送られる8バイトのデータで、Interruptトランスファによって送られます。

コマンドと応答を対にして使う必要はありません。つまり、ホストは間で応答を読み取ることなしに続けてコマンドを送ることもできますし、間でコマンドを送ることなしに続けて応答を読み取ることもできます。

コマンド

コマンドは8バイト固定長で、先頭の1バイトがコマンドの種別を表すコマンドコードとして使われ、残る7バイトにコマンドに対する引数が入ります。実際には常に7バイトの引数が全て使われるわけではなく、コマンド種別ごとに必要な引数の数が決まっています。必要な引数を設定した残りの部分はどんな値でも構いません。

Morphy USB-IO では、8バイトより短いコマンドを送ることはできないようです。(不要な引数は省略し、バイト数を減らしてもいいような気がするのだが、試すとうまくいかない…。)

USB-IOのVer. 2ファームウェアが受け付けるコマンドコードは以下の通りです。(コマンドの名前は、このページの筆者が勝手に付けています。)

0x01: WRITE PORT 0
Port #0にデータを書き込みます。1バイトの引数xを必要とします。このコマンドの実行により、xの8ビットの値がPort #0に書き込まれます。
0x02: WRITE PORT 1
Port #1にデータを書き込みます。1バイトの引数xを必要とします。このコマンドの実行により、xの下位4ビットの値がPort #1に書き込まれます。xの上位4ビットの値は、USB-IOの動作には影響を与えませんが、全て1に設定するべきと思われます。(0に設定するべき、どいうのは誤りと思われます。)
0x03: READ PORT 0
Port #0の値を読んでホストに送る準備をします。引数は必要としません。このコマンドの実行により、Port #0の各ビットの状態が読み取られ、USB-IO内部のメモリに格納されます。このコマンドの実行が完了しても、それだけでは、読み取ったデータがホストに送られるわけではありません。(応答の説明を参照。) Port #0の特定のビットを入力端子として使い、このコマンドによりその値を読み取るためには、このコマンドの実行に先立って、(WRITE PORT 0などを用いて) Port #0の対応するビットに1を書き込んでおく必要があります。
0x04: READ PORT 1
Port #1の値を読んでホストに送る準備をします。引数は必要としません。このコマンドの実行により、Port #0の各ビットの状態が読み取られ、USB-IO内部のメモリに格納されます。このコマンドの実行が完了しても、それだけでは、読み取ったデータがホストに送られるわけではありません。(応答の説明を参照。) 読み取られた値は、下位4ビットになります。上位4ビットの値は、試してみたところ、それ以前にWRITE PORT 1コマンドで書いた値になるようですが、この振舞いが保証されているのかどうか不明です。Port #1の特定のビットを入力端子として使い、このコマンドにより値を読み取るためには、このコマンドの実行に先立って、(WRITE PORT 1などを用いて) Port #1の対応するビットに1を書き込んでおく必要があります。
0x10: WRITE PORT 0 WITH STROBE ON P1.0
Port #0に値を書き込み、Port #1のビット0にストローブ信号を出力します。1バイトの引数xを必要とします。このコマンドの実行により、xの8ビットの値がPort #0に書き込まれます。その後、Port #1のビット0にストローブ信号を出力します。(ストローブ信号については後述します。) ストローブ信号が終了した後も、書き込まれた値は保持されます。つまり、Port #0だけに注目すると、WRITE PORT 0と同じ動作です。このコマンドはMorphy USB-IOのVer.2 ファームウェア (以降?) でだけ使えます。Ver.1 ファームウェアでは無効です。
0x11: WRITE PORT 0 WITH STROBE ON P1.1
Port #0に値を書き込み、Port #1のビット1にストローブ信号を出力します。ストローブ信号を出力するビット位置が異なる点を除いて、WRITE PORT 0 WITH STROBE ON P1.0と同じです。
0x12: WRITE PORT 0 WITH STROBE ON P1.2
Port #0に値を書き込み、Port #1のビット2にストローブ信号を出力します。ストローブ信号を出力するビット位置が異なる点を除いて、WRITE PORT 0 WITH STROBE ON P1.0と同じです。
0x13: WRITE PORT 0 WITH STROBE ON P1.3
Port #0に値を書き込み、Port #1のビット3にストローブ信号を出力します。ストローブ信号を出力するビット位置が異なる点を除いて、WRITE PORT 0 WITH STROBE ON P1.0と同じです。
0x14: READ PORT 0 WITH STROBE ON P1.0
Port #1のビット0にストローブ信号を出力し、Port #0の値を読んでホストに送る準備をします。引数は必要としません。このコマンドの実行により、まずPort #1のビット0にストローブ信号が出力され始めます。ストローブ信号が維持されている時点で、Port #0の値が読み取られ、USB-IO内部のメモリに保持されます。その後、ストローブ信号が終了します。(ストローブ信号については後述します。) Port #0だけに注目すると、READ PORT 0と同じ動作です。このコマンドはMorphy USB-IOのVer.2 ファームウェア (以降?) でだけ使えます。Ver.1 ファームウェアでは無効です。
0x15: READ PORT 0 WITH STROBE ON P1.1
Port #1のビット1にストローブ信号を出力し、Port #0の値を読んでホストに送る準備をします。ストローブ信号を出力するビット位置が異なる点を除いて、READ PORT 0 WITH STROBE ON P1.0と同じです。
0x16: READ PORT 0 WITH STROBE ON P1.2
Port #1のビット2にストローブ信号を出力し、Port #0の値を読んでホストに送る準備をします。ストローブ信号を出力するビット位置が異なる点を除いて、READ PORT 0 WITH STROBE ON P1.0と同じです。
0x17: READ PORT 0 WITH STROBE ON P1.3
Port #1のビット3にストローブ信号を出力し、Port #0の値を読んでホストに送る準備をします。ストローブ信号を出力するビット位置が異なる点を除いて、READ PORT 0 WITH STROBE ON P1.0と同じです。

応答

応答には、2 種類のパターンがあります。

READ系のコマンド (0x03、0x04、0x14〜0x17) を実行した後では、応答は、先頭の1バイト (READ PORT 1 コマンドの後では下位 4 ビットのみ、その他のコマンドの後では 8 ビット全体) に Port から読み取った値が設定され、残りの7バイトにはコマンドの後7ビットがそのままコピーされています。WRITE系のコマンド (0x01、0x02、0x10〜0x13) を実行した後では、応答は、8バイト全部がコマンドのコピーになっています。

なお、Morphy USB-IO のファームウェア自体には、コマンドと応答の対応を取るシカケは含まれません。理由がよくわかっていないのですが、このことが問題になる場合があります。

ストローブ信号

Morphy USB-IOのVer. 2.0以降のファームウェアでは、ストローブ付き入出力のコマンド (0x10〜0x17) が用意されています。ストローブ信号とは、データの入出力のタイミングを外部の回路に通知するための信号で、USB-IOでは常にアクティブ・ロウです。

ストローブ信号は、大雑把に言って、以下のように動作します。

  1. ストローブ信号として使う信号線には、はじめHレベルが出力されています。
  2. データの入出力のタイミングを示すため、信号がHからLに変わります。
  3. 入出力が終わると、またHに戻ります。

ストローブ信号の利用には、以下に注意が必要です。

Windowsでのアクセス方法

(未稿)

FreeBSDでのアクセス方法

(未稿)