6. よく使われるポート

以下は、よく使われる TTL (または CMOS)の汎用論理 I/O ポートについての プログラミング情報です。

もし以下に述べるポートやその他の標準的なポートで本来の使い方(例えば 普通のプリンタやモデムを制御するといったような)をしたいのなら、この HOWTO で述べるようにポートを直接操作するよりも、既存のドライバ(大抵は カーネルにくっついてきます。)を使った方がいいでしょう。 このセクションは PC の標準ポートにLCDディスプレイ(訳注:と言っても 近頃はやりの 14 インチとかのディスプレイのことじゃないですよ。)とか ステッピングモーターとか特製の電子機器をつなぎたいという人を意図して います。

もしスキャナとかいったお店に並べて売ってあるような機器(しかもお店に 出回り始めてからをちょっと経ったようなもの)を制御したいのなら、既に ある Linux ドライバを探してみましょう。 Hardware-HOWTO (訳注:日本語訳は Hardware-HOWTO(日本語訳)です。) などが最初の手がかりとしてはいいと思います。

コンピュータに接続する機器(とか、他にも一般の電子機器)についての より詳しい情報はhttp://www.hut.fi/Misc/Electronics/がお薦めです。

6.1. パラレルポート

パラレルポートのベースアドレス(以下では ``BASE'' と呼ぶことにします。)は /dev/lp0 では 0x3bc、 /dev/lp1 では 0x378、/dev/lp2 では 0x278 になります。 (訳注:Linux カーネル2.2.x以降の parport ドライバをサポートしたシステムでは lp デバイスファイルとベースアドレスが必ずしも対応しているわけではありません。 詳しくはカーネル付属文書 parport.txt を参照してください。) 通常のプリンタポートとして動作させたいだけでしたら、 Printing-HOWTO(訳注:日本語訳は Printing-HOWTO(日本語訳)です。)を 読むのがいいでしょう。

ほとんどのパラレルポートには以下に述べる標準的な出力専用モードに加えて、 「拡張」双方向モードがあります。これに関すること、また最近の ECP/EPP モード(さらには汎用の IEEE1284 規格)については、 http://www.fapo.com/http://www.senet.com.au/~cpeacock/parallel.htmlを参照してください。 ユーザモードのプログラムでは IRQ や DMA が使えませんので、ECP/EPP を使う ためにはおそらくカーネルドライバを書かなければならないでしょう。 誰かがそういったドライバを書いているだろうとは思いますが、私は詳しいこと は知りません。

BASE+0のポート(データポート) は、ポートの データ信号を制御します。 (D0 〜 D7 はビット 0 〜 7 に対応します。状態 : 0 = low (0V)、1 = high (5V))。 このポートに対するライトはデータをラッチして外部のピンに出力します。 標準または拡張ライトモードの場合には、リードすると、最後にライトされた データが読み出されます。 拡張リードモードの場合には、外部デバイスからのデータが読み出されます。

BASE+1のポート(ステータスポート) は リードオンリーで、以下のような入力信号のステータスを返します:

BASE+2のポート(制御ポート)はライトオンリー (リードした場合、最後にライトしたデータを返す。)で、 以下のステータス信号を制御します:

ピン接続 (25 ピンの D-sub メスコネクタ) (i=input, o=output):
1io -STROBE, 2io D0, 3io D1, 4io D2, 5io D3, 6io D4, 7io D5, 8io D6,
9io D7, 10i ACK, 11i -BUSY, 12i PE, 13i SLCT, 14o -AUTO_FD_XT,
15i ERROR, 16o INIT, 17o -SLCT_IN, 18-25 Ground

IBM の規格によれば、1, 14, 16, 17 番ピン(制御出力)は、4.7kオームで 5V に プルアップされたオープンコレクタドライバ (シンク(吸い込み) 20mA, ソース (吐き出し) 0.55mA, ただし、ハイレベルの出力は プルアップの 5V) その他のピンについては、シンク(吸い込み) 24mA, ソース(吐き出し) 15mA, ハイレベル出力は最小 2.4V, ローレベルの出力は最大 0.5V。 IBM 以外のパラレルポートではおそらくこの標準とは少々違う場合もあるでしょう。 これに関するもっと詳しい情報は http://www.hut.fi/Misc/Electronics/circuits/lptpower.html をご覧ください。

最後に注意: グランド(接地)には気をつけましょう。私はコンピュータが稼働中に コネクタを接続したせいで、パラレルポートを何個も壊してしまった経験があります。 これを考えると、マザーボードに乗っているのではない(拡張カード上の)パラレル ポートを使うのがいいかもしれませんね。 (標準的な安い「マルチI/O」カードを使えばあなたのコンピュータに二つめの パラレルポートが作れます。 必要のない(パラレルポート以外の:訳注)ポートは disable してしまえばいいです。 拡張カードのパラレルポートのI/Oアドレスを空いているところに設定しましょう。 IRQ は使う予定がなければ気にする必要はありません。) (訳注: 各機器のフレームグランドは、ちゃんととりましょうね。)

6.2. ゲーム(ジョイスティック)ポート

ゲームポートはポートアドレス 0x200-0x207 です。 普通のジョイスティックを制御するなら、多分、Linux カーネルにくっついてくる ドライバを使った方がいいですよ。

ピン接続 (15 ピンの D-sub メスコネクタ):

+5 V ピンはマザーボードの電源に直接接続されているようですので、 (マザーボードの作りや、電源、ゲームポートにもよりますが)非常に 大きな電力を供給することができるはずです。

このポートには二つのジョイスティックを接続できますが、デジタル入力は、 これらのボタンからの入力です。 (ジョイスティック A とジョイスティック B それぞれに二つずつボタンがあ ります。) これらは通常の TTL レベルの入力で、以下で述べるステータスポート(以下 に記述)から現在の状態を読み出すことができます。 実際のジョイスティックではボタンが押されていると low (0V) を、そうで なければ high (1K オームの抵抗を通じて 5V 電源にプルアップ) が読み出 されます。

いわゆるアナログ入力というのは、実際には抵抗値を計っているのです。 以下でその仕組みを述べます。 ゲームポートには4本の入力それぞれにワンショットマルチバイブレータ が接続されています。(全体(4本)で 558 チップ一つ) それぞれの入力について、入力ピンとマルチバイブレータの出力の間に 2.2K オームの抵抗が、マルチバイブレータの出力とグランドの間に 0.01uF のタイミング用コンデンサが接続されています。 実際のジョイスティックには、X と Yの両方の軸にそれぞれポテンショメー タがあり、+5V とそれぞれの入力ピンに接続されています。 (AX, AY がジョイスティック A に、BX, BY がジョイスティック B に対応し ます。) (訳注: 回路図はこんな感じかな:
+5V
 |       ^
 |      /          2.2Kオーム
 +---/\/\/\--IN----/\/\/\------+
       /                       |
 ポテンショメータ              |
                  +---------+  |
                  | Multi   |  |
                  | vib.   Q|--+
                  |         |  |
                  |         |  |
                  |         |  |
                  |         | === 0.01uF
                  |         |  |
                  +---------+  |
                               |
                              GND
)

マルチバイブレータが作動すると、その出力を high (5V) にドライブし、 それぞれに接続されているタイミングコンデンサの電位が 3.3V になるまで 待ち、その後に出力を low にします。 この結果、マルチバイブレータの出力が high の時間はジョイスティック中 のポテンショメータの抵抗値に比例します。 (つまり、それぞれの軸のジョイスティックの位置を表します。) 抵抗値は以下の式のとおりです:

R = (t - 24.2) / 0.011,

ここで、R は ポテンショメータの抵抗値(オーム)、t は high の時間(マイ クロ秒)です。

とまあ、こういうわけですので、アナログ入力を読み出すためには、以下で 述べるようにまずポートにライトして、マルチバイブレータを作動させる必要が あります。 その後に4つの軸の状態をポーリング(ポートを繰り返し読み出す)し、それぞれ のポートが high から low になるまでの時間を測定します。 このポーリングには非常に CPU タイムを消費しますし、(通常のユーザモードの) Linux のような非リアルタイム・マルチタスクシステムではその結果はあまり正 確ではありません。 ポートを絶え間なく読み出すことはできないからです。 (カーネルレベルのドライバを使うか、ポーリングの間、割り込みを禁止すれば いいのですが、これは更に多くの CPU タイムを食います。) 信号が low になるまで長い時間(数十ミリ秒)かかるのが分かっているなら、ポー リング前に CPU タイムを他のプロセスに明け渡すよう usleep() を呼ぶこともできます。

さて、アクセスする必要のあるポートはただ一つ、0x201 (他のポートアドレスはこの ポートと同じようにふるまうか、なにもしないか、のどちらか)です。 このポートに対するライト(書き込むデータはなんでも良いです。)によって マルチバイブレータが作動します。リードすると入力信号の状態が返ります:

6.3. シリアルポート

コンピュータと接続させたい機器が RS-232 みたいな仕組みを持っているなら、 その機器との接続にシリアルポートを使うといいでしょう。 Linux のシリアルドライバはほとんどありとあらゆる応用が効きます。 (シリアルポートを直接操作するなんてしない方がいいです。そんなことするなら 多分カーネルドライバを書かなければならないハメになりますよ。) このドライバとっても汎用性が高いので標準でない bps レートを使うといった こととかも問題ではありません。

Unix システムでシリアルポートを使うプログラムのより詳しい情報については termios(3) マニュアルページやシリアルドライバの ソースコード(linux/drivers/char/serial.c) 、またhttp://www.easysw.com/~mike/serial/を参考にしてください。