プリンターポートを用いたGPIBの制御

GPIBを他のインターフェースを用いて制御しようという試みは,以前から行われています. プリンターポートを用いての制御もどこかにあるだろうと思って調べてみましたが,見つけられませんでした. もしかしたら調べ方が足りないだけで,どこかにあるのかも知れませんが,無いのなら作れないのかどうか検証してみようというように考えました. 以下はその記録です.

GPIBの概要

GPIBの信号線は,8本のデータバス及び8本のシステムバスから成り立っています. これらはいずれも入出力ができます. データの伝送は三線ハンドシェイクによって行われ,この際にはトーカー側では一つの出力(DAV)と二つの入力(NRFD, NDAC)が用いられます. リスナー側では逆に一つの入力と二つの出力となります. システムバスとしては,これ以外に, コマンドを発信するときに用いられるATN, 発信データの終わりを示すEOI, サービスリクエストを伝えるSRQ, 制御する装置をリモートにするためのREN, インターフェースの初期化を行うIFC, があります. これらの中で,SRQはコントローラによって受信され, ATNとIFCとRENはコントローラ側から出力されるので, コントローラからみると,入出力のどちらかのみしか行われないことになります. なお,信号はいずれもTTLレベルの負論理です.

プリンターポートの概要

プリンターポートは,8本のデータバスと9本のシステムバスからなります. データバスはモードによりますが,出力のみまたは入出力が可能です. システムバスのうち5本(ACK, BUSY, PE, SLCT, ERROR)は入力で,4本(STROBE, AUTOFXINIT, INIT, SLCTIN)は出力です. なお,信号はいずれもTTLレベルで,データバスは正論理ですが,システムバスは正論理のものと負論理のものがあるようです.

GPIBとプリンターポートの違い

双方向のプリンターポートとコントローラー側から見たGPIBで用いられる信号線の数を比較すると,次の表のようになります. 幸いにしてデータバスの数は一致しているのですが,プリンターポートには入出力とも可能な信号が不足しています. この不足分を余った入力と出力を利用して補うことができれば,プリンターポートからGPIBを制御することが可能になるわけです. おそらく論理回路などを用いて細工をすれば,これは可能でしょうが,以下ではできるだけシンプルな構造にすることを第一に考え,プリンターポートでGPIBを制御する試みについて触れることにします.
GPIBプリンターポート
データバス880
入出力40-4
入力15+4
出力34+1

トーカーのみでの制御

コントローラはアドレスの指定などをしなければならないので,必ずトーカーになります. 一方で,制御する装置によっては,コマンドを送るだけで,データを受信しない場合もあります. つまり,コントローラがトーカーのみで,リスナーにならない場合があるわけです. そのような場合には,ハンドシェイクに用いられる3本の信号は,入力または出力のどちらかのみに用いられることになります. このように考えて,信号線の数を比較したのが次の表です. プリンターポートには,入出力信号であるEOIに相当する部分のみが不足しますが,それ以外の信号の数は十分になります. また,データの終わりを表すEOIは必ずしも必要でなく,適切なデリミタを送信してやれば,ほとんどの装置は制御できます. つまり,EOIを無視すれば,プリンターポートでの制御が可能になるのです. しかし,この場合には,適切なデリミタの設定が不可能なバイナリデータの伝送は不可能になります. もう一つの方法としては,7bit信号しか送らないことを考慮して,データバスの最後のbitをEOIに割り当ててしまうということができます. この場合にもバイナリデータは送れませんが,EOIをきちんと処理できるので,安心できます. 前者の方法でトーカーのみを可能にするスクリプトをrubyで書いたものがprngpib.rbです. このスクリプト中に書かれているように,プリンターポートのD-sub25pinからGPIBのアンフェノール24pinにつながるようなケーブルを作成さえすれば,rubyからGPIBの制御が可能になります.
GPIBプリンターポート
データバス880
入出力1(EOI)0-1
入力35+2
出力440

リスナーも可能な制御

コントローラーがリスナになるためには,ハンドシェイクのための信号のやりとりが必要になります. 入力が1本(DAV)と出力がもう2本(NRFD, NDAC)必要なのです. プリンターポートには出力が少ないために,単純にはそのための信号を余分に用意することができません. ここで,GPIBのシステムバスのうち,コントローラから出力される信号線について考えてみましょう. 出力される信号は,DAV, ATN, REN, IFC, EOI, NRFD, NDACの7本で,トーカーの場合には前の5本のみが必要で,前に示したスクリプトではEOIも無視してプリンターポートの4本の出力でまかなったのでした. DAVはトーカーになるためには絶対必要で,ATNもコマンドを送らなければならないので欠かせません. すると,残る出力は2本です. 一方,IFCは通常は始めに使われるだけでほとんど使われません. 実際,使わなくてもほとんど支障がありません. また,RENは常にONにしておけば,装置をリモートでコントロールすることができます. ローカルにする必要がなければ,GNDに落としておけば良いのです. さらに先に説明したように,EOIはデータバスの1bitを削って作ることができます. このようにすれば,リスナになるために必要なNRFDとNDACに出力を割り当てることができるのです. ただし,当然のことながら,いくつかの制約ができます. それらは,インターフェースクリアーができないことと,プログラムから装置をローカルにできないことと,バイナリデータの転送ができないことです. しかし,これらは多くの装置の制御においては,それほど重要なことではないと考えられます. さて,ここで最後に問題になるのは,GPIBでは入出力の双方向の信号を,プリンターポートでは,入力と出力の信号を組み合わせて実現するという点です. ハンドシェイクに用いられる3本の線についてこれを行わなければいけないのです. できれば電子回路は使いたくはないのですが,これは仕方がありません. NPNトランジスタを用いて次のようにすることにしました. まず,GPIBの信号と入力は短絡します. そして,入力にコレクタを,出力にベースを,エミッタをGNDに繋ぎます. 出力信号は通常は0Vにしておくと,トランジスタには電流は流れないので,GPIBの信号が入力に入ります. 出力を5Vにすると,コレクタからエミッタに電流が流れてGPIBの信号が0Vになります. NPNトランジスタとしてはC945を用いました. このようにしてGPIBを制御するスクリプトをrubyで書いたものがprn2gpib.rbです. ケーブルに三つのトランジスタを組み込んだものを作成して下さい. 最後に注意しておきたいのが,プリンターポートのモードです. 双方向の通信をするためには,BIOSの設定でbi-directionalまたはEPPにしておく必要があります.

まとめ

いくつかの制約はありますが,プリンターポートを用いてGPIBを制御することが可能であることが実証されました. 比較的容易にこのようなことができるという事実が,あまり知られていないのが不思議なくらいです. ケーブルは自作する必要がありますが材料費は千円ぐらいではないでしょうか. 制御するプログラムはrubyでしか書いていませんが,別の言語でも当然書くことはできるでしょう. もっとも,rubyで動けば他の言語で書く必要はないように思いますが. ご意見,ご感想などがありましたら,メール頂ければ幸いです.