[Japanese|English]

USB-IOについての感想や希望など

感想

実際に購入し、組立て、使ってみた感想を順不同に書いておきます。

希望

USB-IOはなかなかヨイのですが、使っているといくつか気になるところも出てきます。いくつか希望を書いてみます。

ドーターボード対応

USB-IOは単体では役に立たないため、他の回路と組合せて使うことになります。外づけの回路が大きいと、そちらをメインのボードとして、USB-IOを上に重ねるような構成にしたくなります。ところが、じっさいにこれをやろうとすると、少々困ります。

大抵はメインのボードの方が大きくなるし、USBのコネクタにはそれなりに力もかかるため、USBのコネクタをメインボード側につけたくなりますが、そのためには、USB-IO側のコネクタの取りつけ穴にはコンタクトピンを立ててメインボードと繋ぐことになります。現在のUSB-IOのプリント板だと、これは2×2のピンヘッダになります。これよりは、1x4のピンが使えた方が、部品の入手も簡単で幸せです。たぶん、穴だけ余分に開けておいて、どちらにも使えるようになっているとベストだと思います。

ストローブ信号の作り方

Ver. 2 ファームウェアの新機能に、ストローブ付き入出力コマンド (コマンドコード 0x10〜0x17) があります。これは大変便利なのですが、ファームウェアの実装にちょっとした問題があります。

USB-IOがストローブ信号を作るとき、Port #1の他のビットを変えずに特定の1ビットだけを変化させる必要がありますが、CY7C63001AではPort #1の全ビット分をまとめて書込まなければなりません。そこで、Ver. 2ファームウェアでは、まずPort #1を読み取り、ストローブを出すビット以外のビットのついてはそのまま書き戻すようにしています。

この方法は、出力として使っているビットについてはうまく機能しますが、入力についてはうまくいきません。

仮に、Port #1のビット3を入力として使い、同時に、Port #1のビット0にストローブを出したいとしましょう。CY7C63001Aでは、入力として使いたいビットには1を書いておかなければなりません。そこで、ホストソフトウェアでは、Port #1のビット3に予め1を書いておくように制御します。ところが、たまたまストローブ信号を出した時点で、Port #1のビット3から入力している信号が0だと、ストローブが完了した時点では、Port #1のビット3には0が書込まれてしまいます。このままでは実際の入力を読み取ることができません。

おそらく、「現在の値」を知るためにポートの値を読むというのはうまい方法ではないのでしょう。本来は、ホストからのWRITEコマンドによってPort #1に最後に書いた値を覚えておき、それを基準にビット3だけを適切に変えた値を書込むべきなのだと思います。

当面の対処方法として、ストローブ付きコマンドを使うときにはPort #1を入力に使わない方がいいと思います。

読取りコマンド

USB-IOには、ポートの状態を読み取るためのコマンド (コマンドコード0x03と0x04) があります。このコマンドは、ポートの状態 (値) を読み取りますが、その時点では読み取った値をホストに通知することはしません。読み取った値はマイコン内部のメモリに記録され、次にホストからインタラプトトランザクションが要求された時点で渡されます。

この動作は冗長だと思われます。

それよりは、インタラプトトランザクションが要求された時点でポートの状態を読み取り、即座に送り返す方が便利で確実と思われます。この場合、読み取るべきポート (Port #0またはPort #1) をホストから指定することができませんが、送り返すデータは8バイトありますから、常に両方のポートを読み取って2バイトまとめて返せばいいでしょう。

ストローブ付き入力は読み取るタイミングや生成するパルスの数が重要なので、コマンドを実行した時点で一旦メモリに格納するという現在の形式を維持する必要があります。しかし、ストローブ付き入力に対する応答の場合でも、インタラプトトランザクションの過程で読み取った値を格納する場所 (オフセット) とは別の場所にストローブ付きで読み取った値を格納してホストに応答すれば、特別扱いする必要はありません。

コマンドと応答の対応

USB-IO で入力系のコマンドを使用する場合、実際に読み取った値は引き続く応答 (インタラプトトランザクション) によって通知されます。ところが、コマンドを実行した直後の応答には、読み取った値が格納されていない場合があるようです。この場合、何もコマンドを要求せずに、単に応答を読みつづける (インタラプトトランザクションを繰り返す) と、そのうち、読み取った値に変わります。

この動作は、一見すると、コマンドの処理に時間がかかり、それが完了する前に (まだ受信していない) 応答を読み取っているように思えます。ところが、実際にテストすると、単純に応答が遅れる以上に、何かヤヤコシいことが起きているようです。原因がUSB-IO側にあるのか、Windowsにあるのか不明です。 (アナライザを持っていないので、本当に USB の線上で何が起きているのかを調べることができない。) 他のプラットフォームでは、どうなのでしょうか。

当面の対処として、現在のクラスライブラリでは、コマンドを要求する時に、未使用バイトにコマンド発行の連番を入れており、応答の連番と一致することを確認するようにしています。(OLTP での、トランザクション ID のような使い方をします。) USB-IO では、コマンドは常に 8 バイトをまとめて送るため、未使用バイトがあります。未使用バイトは、ファームウェアの動作上は単に無視されますが、捨てられてしまうわけではなく、応答の対応するバイト位置にそのままコピーされます。発行連番は、USB-IO ファームウェアの、この性質を利用して実装しています。

追記:

その後、この動作は、ドライバが、アプリケーションの ReadFile の呼び出しと独立に、インタラプトパイプのポーリングと先読みを自動的に行うことに起因する、正常な動作である (らしい) ことに気づきました。