プログラム講座 中級編23

- 他機種とのシリアル通信 -

 中級編23です。今回は「他機種とのシリアル通信」について説明します。この講座に限らずMac関係のページでは珍しいネタかもしれません。




RS232C,RS422
 シリアル通信といっても他機種とMacをRSケーブルで接続するだけです。多くの機種にはRS232Cというポートが用意されています。これに対してMacはRS232Cと上位互換性のあるRS422ポートを搭載しています。「そんなポート(接続口)あったっけ?」という人もいるかもしれません。これは単にプリンタポートとモデムポートを示しています。このポートはアップルトークやTCP/IPなど、複数のプロトコル/データを介するだけのものです。
 PC9801やFM-R,MZ,など昔のマシンのデータをなんとかMacに持っていきたい事があります。この場合、以下のような方法があります。

(1) 3.5inch FD(MS-DOSフォーマット)を利用する
(2) 通信を利用する
(3) 一度プリントアウトしOCRで読み込む
(4) 笑ってあきらめる

 通信を利用する場合、マシンが近くにある場合は、そのまま直結してやればデータのやりとりが可能になります。直結する場合は「クロスケーブル」を使用して下さい。RS232Cケーブルには「クロスケーブル」と「ストレートケーブル」があります。モデム等外部機器とのやりとりにはストレートケーブルが使用されますので、モデムケーブルを接続しても正常に動作しません。
 通信の第2の方法としてはインターネットやニフティサーブを中継する方法があります。このようにすれば、問題も少なくデータをやりとりする事が可能になります。しかし、昔のマシンではニフティサーブに接続する事すら難しいものもあります。1台経由しただけでなく、数台経由しないとデータを持ってくる事が不可能なマシンもあります。*1

注釈
例えばシャープのMZ-700ではカセットが標準なため、一度X1turboを経由してカセットから5inch FDにコピー、その後X68000,PC9801で3.5inchへの変換が可能なマシンを経由、さらに1.2MBフォーマットしか扱えない場合はPC-9821等を経由しなければなりません。インチキな方法としてはカセットのデータを音声としてサウンドファイルに変換後、バイナリデーターにするという方法もあります。



ボーレート等の設定
 2機種間でデータをやりとりする場合、いくつかの約束事を設定しておかなければなりません。特に「ボーレート」は非常に重要です。ボーレートというのはデータを転送する速度の事でFuture BASICでは以下のボーレートを設定できます。

110300*1200*
18002400*3600
4800*72009600*
192003840057600

 *印が付いているものは古い機種でもサポートされている(可能性が非常に高い)ボーレートです。Z80マシンなど処理速度の遅いマシンでは、4800、2400、1200あたりでやりとりするのが良いでしょう。それでも駄目な場合は300まで落としてみましょう。それでもうまくいかない場合は、ケーブルの結線ミス(ストレート、クロス)、プログラムのミス、Macでアップルトークが使用されている等を確認しましょう*1。

 設定はボーレートだけでなく転送するデータのビット数を指定しなければなりません。特に漢字を含むテキストデータ(JISコード以外)や画像データ、バイナリデータでは「8ビット」を指定しないといけません。Future BASICでは初期設定が7ビットになっているため、英文テキスト以外は正常に転送できなくなってしまう可能性が大です(ものによりますし、送り方にもよります)。

 ストップビットは通常1を指定すれば良いでしょう。また、場合によってはハンドシェークの設定も必要になります。

今回はMac と MZ-2500間でデータのやりとりを行いました。MZ-2500はtermコマンドで何もプログラムしなくてもMacとやりとりする事が可能です。今回はMZ-2500を使ってMacを制御するという一風変わった処理を行ってみました。

*1
シリアル通信を行う場合は、アップルトークの使用をオフにしておかなければなりません。セレクタでアップルトークの使用をオフにすればOKです。



プロトコル
 さて準備はできましたが、2機種間でデータをやりとりする場合、どのようにデータを転送するかを決めておかなければなりません。例えば先頭の文字がinst:だったら命令、data:だったらデータそのものといった具合です。一方通行的にデータを送信するだけで、なおかつエラーも発生しない、完璧な場合は特に考慮する事はないでしょう。しかし、データの書き込みや表示などに費やす時間はかなりのもので、その間にデータが送られてきてしまうとデータを取りこぼしたりバッファがあふれてしまう可能性もあります。そのために、相互でデータを送信可能かどうか、受信可能かどうかを確認する事が必要になります。このように、相手とデータをやりとりするものを「プロトコル」といいます。AppleTalk,TCP/IPなどはプロトコルの名称です。つまり、どのようにデータをやりとりするか、その規格と言えます。

 もし、プログラムが組めない状況であればプロトコルが違うのを泣く泣くあきらめるしかありません。しかし幸いにしてFuture BASICがありますから、自分で勝手にプロトコルを決めてしまって好き勝手に行えばよいのです。別に難しく考えることはなくデータ垂れ流しでも良いのです。なんといっても最大の目的は「データを転送すること」であって「プロトコルを決めること」ではないからです。初心者には変なアドバイスを受けてしまって「プロトコルを決める事が重要」になってしまい本来の目的である「データを転送すること」が二の次になってしまう事があります。

 今回のプログラムはデータを送り終わったら「機種名:end」の一行を送るだけです。またバイナリデータのやりとりは行いません。



制御コマンド
 MZ-2500でMac 8500/132を制御するのですが、今回は以下のコマンドを用意しました。

コマンド名内  容
endプログラム終了
clsウィンドウ内容消去
openファイル選択ダイアログを表示後、MZにデータ転送
saveファイル保存ダイアログを表示後、MZのデータを保存
shutdownMacの電源を切る

 他にもリスタートやいろいろなコマンドを追加する事が出来ます。例えばPICT画像を選択してデータを転送しMZに表示させることもできます(過去にやりました^^b)。その逆も当然可能です。
 また面白いことにこのようにするとMacの不得意とされるバッチ処理も可能になります。起動時に最初にシリアル通信を行うプログラム起動させておけば良いだけですし、今までとは違った使い方もできるかもしれません。



終わりに
 普通はMac8500でMZ-2500(8bitマシン)を制御するというものですが、今回は逆にしてみました。MZでコマンドを入力すると、それに反応してMacが動作するというのは、意外と面白いものです。今回は異機種間接続でしたが、当然モデムポートにもデータを出力する事ができます。さすがにインターネットのブラウザを作ることはシリアル通信では無理ですがNiftyServeクラスであればFuture BASICを使って自作したソフトでやりとりする事が可能です。時間がある人は試しに作ってみるのも良いのではないでしょうか。自分で作れば、自由に拡張、改造できますし良い勉強になるでしょう。
 今回掲載されているMZ-2500のプログラムは、このシリアル通信プログラムを利用してMZから転送したものです。



今回のプログラムリスト
●Macintosh Future BASIC 1.0.x,2.13,2.3
thePort = _modemPort END GLOBALS LOCAL FN initSerial WINDOW OFF WINDOW #1,"Let's Communication",(8,40)-(320,400),_doc TEXT _applFont,12 OPEN "C",#thePort,4800,_noParity,_oneStopBit,_eightBits,16384 END FN '-------------------------------------------------- ' "コマンドを受信する" '-------------------------------------------------- LOCAL FN getCommand$ moji$ = "" DO READ #thePort,a$;0 IF ASC(a$) > &H20 THEN moji$=moji$+a$ UNTIL a$ = CHR$(13) END FN = moji$ '-------------------------------------------------- ' "ファイルを送信する" '-------------------------------------------------- LOCAL FN fileopen filename$ = FILES$(_fOpen,"TEXTEPSF",,vRefNum) LONG IF filename$<>"" OPEN "I",#3,filename$,,vRefNum WHILE NOT EOF(3) LINE INPUT #3,sd$ PRINT sd$ PRINT #thePort,sd$ moji$ = FN getCommand$: ' "mz:nextの文字を受信" WEND CLOSE #3 END IF END FN '-------------------------------------------------- ' "ファイルを保存する" '-------------------------------------------------- LOCAL FN filesave filename$ = FILES$(_fSave,"保存ファイル名:","",vRefNum) LONG IF filename$<>"" DEF OPEN "TEXTttxt" OPEN "O",#3,filename$,,vRefNum DO PRINT #thePort,"mac660av:send" moji$ = FN getCommand$: ' "テキストを受信" PRINT moji$ PRINT #3,moji$ UNTIL moji$="mz:end" CLOSE #3 END IF END FN '-------------------------------------------------- ' "コマンドを処理する" ' "end -> 終了" ' "cls -> 画面消去" ' "open -> ファイルオープン後、内容送信" '-------------------------------------------------- LOCAL FN main endFlag = _false WHILE endFlag = _false cmd$ = FN getCommand$: ' "コマンド入力を待つ" PRINT cmd$ IF cmd$="end" THEN endFlag = _true IF cmd$="cls" THEN CLS IF cmd$="open" THEN FN fileopen IF cmd$="save" THEN FN filesave IF cmd$="shutdown" THEN SHUTDOWN PRINT #thePort,"mac660av:end" WEND END FN FN initSerial FN main CLOSE #thePort ●MZ-2500 BASIC M25
10 init "com1:4800,N81" 20 open "o",#1,"com1:" 30 open "i",#2,"com1:" 40 *LOOP 50 input "Command:";CMD$ 60 if CMD$="save" then *SENDTEXT 70 print #1,CMD$ 80 repeat 90 line input #2,MSG$ 100 print MSG$ 110 print #1,"mz:next" 120 until MSG$="mac660av:end" 130 goto *LOOP 140 '------------------------ 150 'sendtextfile 160 '------------------------ 170 *SENDTEXT 180 input "filename:";FILENAME$ 190 open "i",#3,FILENAME$ 200 print #1,"save" 210 while not eof(3) 220 input #2,MSG$:'"mac660av:send"command 230 line input #3,A$ 240 print #1,A$ 250 wend 260 input #2,MSG$:'"mac660av:send"command 270 print #1,"mz:end" 280 close #3 290 goto *LOOP