以前、PC-6001のジョイスティックポートでRS-232C通信を試してみる記事を公開しましたが、ハード工作の方法が分かりにくい箇所があったので、記事や回路を見直して、少しだけ実用的に使えるようにしてみました。
以下の説明では、WindowsとPC-6001をつなげる方法で説明をしていますが、原理的にはRS-232Cが使えれば、MacでもLinux機でもRaspberryPiでも動かすことが出来ます。
注意点1) PC-6001初代機とPC-6601で動作確認が取れています。SR系では動かないかもしれません。
注意点2) 異なる2つの環境で動作確認が取れていますが、接続機器やPC-6001の動作状態によっては安定した通信が出来ない場合があります。
ジョイスティックポートでRS-232C通信を行うにあたり、変換ケーブルを作成する必要があります。
必要なものは以下の通りです。
RS-232C TTLコンバータ |
PC-6001ジョイスティック端子用コネクタと9芯ケーブル |
RS-232C USB変換器(既存品) |
RS-232Cケーブル(無くてもOK) |
以前の説明では、RS232Cのレベル変換用のパーツを集めてハンダ付けを行いましたが、今では変換回路一式が積まれている、コンパクトな変換基板があります。これがなんと、DSUBコネクタ内に収まってしまうのですね。この基板ですが、送受信を入れ替えているようです。なので、クロスケーブルではなくストレートケーブルで相互接続します。
PC-6001に挿し込むジョイスティック端子は、奥行きがあり、一般的なDSUB 9pinコネクタはつながりません。そこで、使えなくなったメガドライブ用コントローラのケーブルや、メガドライブ用の延長ケーブルを加工することで、PC-6001につなげることが出来ます。
ケーブル作成には、ケーブルの加工やハンダ付けが必要なので、それなりの手間はかかります。 ハンダ付けはちょっと・・・という方は、MSXで同じような仕組みを実現されている「ジョイジョイファイルシステム」のような方法でも可能かもしれません。ただし、以下で説明している内容では、RTS/CTS信号を使った制御を行っているので、MSX版と同じパーツを使うことは出来ません。
この記事では、PC-6001ジョイスティック端子と通信用の信号線の割り当ては以下のようにしてあります。
端子番号 | 用途 | P6からみた入出力 |
---|---|---|
1 | RxD | 入力 |
2 | CTS | 入力 |
3 | 未使用 | |
4 | 未使用 | |
5 | +5V | 出力 |
6 | 未使用 | |
7 | RTS | 出力 |
8 | TxD | 出力 |
9 | GND |
ジョイスティック端子の番号は、PC-6001を横から見た時の並びです。(PC-6001のマニュアルに記載されている順)
挿し込む側からみると、このような並びになります。
ケーブルと端子の関係はテスターなどを使って通電確認してください。私の場合、たまたまDSUB9ピンの受け側パーツがあったので、それを使いました。
PC-6001側につなぐDSUB側のテーブルは適当な長さに切ります。適当な長さというのが具体的にどれくらいかというのは難しいのですが、とにかく短いほどいいです。ただ、短すぎるとハンダ付け作業が大変になりますし、PC(Windows)とPC-6001を繋いだ時に不便だったり、ケーブルを無理に引っ張った時に断線しやすくなるので、自分が扱うのにちょうどいい長さにしてください。
TTLコンバータの基板には、接続信号が書かれています。VCCは+5Vの事です。RxDとTxDは矢印の記号の向きに合わせてはんだ付けします。PC-6001から出ていく方がTxD(8番ピン)、PC-6001が受け取る側がRxD(1番ピン)になります。CTS(2番ピン)とRTS(7番ピン)は表記の通りに接続します。
DSUBのケーブルの被覆をはがして、ハンダ付けすれば終わりです。ケーブルの被覆は、ワイヤーストリッパーなどを使うと便利です。また、DSUB 9ピン端子のうち使うのは6ピンなので、残り3本の芯線が回路や他のケーブルに接触しないように注意してください。
完成。
PC(Windows)に接続するUSBタイプのRS-232C変換器ですが、RTS/CTS信号に対応していないものがあるようです。私が使っているのは、CG-USBRS232Rという、かなり古い製品です。
Amazonで取り扱いがある安価なものでは、こちらのケーブルがRTS/CTSにも対応しているそうです。
RS-232Cの規格では、最大15mまでの長さのケーブルを使うことが出来るので、PC(Windows)とPC-6001が離れている場合は、中間にRS-232Cケーブルを挟むとよいでしょう。ケーブルを買う時は、接続口のオス/メス形状に注意してください。また、先に説明した通り、RS-232C TTL変換基板は送受信の信号を入れ替えているようなので、ストレートケーブルで接続してください。
ここではWindowsを使った説明をします。
RS-232C変換器をPC(Windows)に接続してドライバをインストールします。製品によっては、OSが自動認識&必要なドライバのインストールをしてくれます。
PC(Windows)側の通信ソフトですが、RTS/CTS信号の状態を表示してくれるAcknowrichが便利です。
Acknowrichを起動し、メニューのファイル→シリアルデバイスを開く...から、USB変換器に割り当てられているCOMポートを選択します。COMポートの確認は、コントロールパネルのデバイスマネージャから確認できます。
通信設定では、CTSとRTSにチェックが入っていることを確認してください。
通信ウィンドウでは、38400bps, Parity=NONE, StopBit=1.0, Length=8に切り替えてください。設定を変更するには、変更したい箇所でマウスの右ボタンを押すと選択項目が表示されます。COMポート番号が変更された時などに、ここの設定が違う値に切り替わってしまうことがあるようです。
PC-6001側の受信テストプログラムですが、以下のようなコードになります。
; 受信速度38400bps
; 00~FFの値が送られてくるのを受信する
; 順番通りに受け取れたらOK
;
; BASIC ROM ROUTINE
PUTCHAR EQU 1075H
CLS EQU 1DFBH
LOCATE EQU 116DH
PUTSTR EQU 30CFH
; マシン語開始番地
; RAM 32K
; P6ファイルの先頭部分に、10 EXEC&H8410のBASICプログラム付き
ORG 08410H
CALL AYSET
CALL CLS
XOR A ; キークリック音をオフにする(CONSOLE命令第4パラメータ)
LD (0FA2DH),A
DI
CALL CHECK255
EI
RET
;----------------------------
;----------------------------
CHECK255:
LD BC,0000H ; Breg Loop Counter, Creg Check Data
CHECK255_1:
PUSH BC
; LOCATE 1,1:PRINT HEX$(Creg)
LD HL,0101H
CALL LOCATE
CALL OutHex8 ; in:Creg
LD A,02H ; BUSREQ禁止
OUT (93H),A
CALL RECV ; 受信待ち~受信処理
POP BC
CP C
JR NZ,check_error
LD A,03H ; BUSREQ許可
OUT (93H),A
INC C
DJNZ CHECK255_1
LD HL,0102H
CALL LOCATE
LD HL,sucmsg
CALL PUTSTR
RET
check_error:
; Areg:間違っている受信データ
PUSH AF
LD A,03H ; BUSREQ許可
OUT (93H),A
; LOCATE 1,1:PRINT HEX$(Creg)
LD HL,0102H
CALL LOCATE
pop AF
LD C,A
CALL OutHex8 ; in:Creg
LD HL,0103H
CALL LOCATE
LD hl,errmsg
CALL PUTSTR
RET
;----------------------------
; TEST結果用
crlf:
DB 0DH,0AH,00H
errmsg:
DB "ERROR.",00H
sucmsg:
DB "SUCCESS.",00H
;----------------------------
; disp HL(HEX)
DispHLhex:
LD C,H
CALL OutHex8
LD C,L
;----------------------------
; disp C(HEX)
OutHex8:
LD A,C
RRA
RRA
RRA
RRA
CALL OutHex8_1
LD A,C
OutHex8_1:
AND 0FH
ADD A,90H
DAA
ADC A,40H
DAA
CALL PUTCHAR
RET
;----------------------------
;----------------------------
; 1Byte受信処理
; Aregにデータが入る
RECV:
; 9bit(データ8bit + STOP1bit)受信するためループだけど、
; STOP Bitは別に読まなくてもいいよね...
LD B,8
; 後の処理の高速化用
LD C,01H
LD E,0EH
; RTS信号をONにする
CALL RTSON ; RETの分だけ 10CLK [11CLK]
; portAから入力する
LD A,E ; 4CLK [ 5CLK]
OUT (0A0H),A ;11CLK [13CLK]
WAIT_BIT:
; ひたすらスタートビットを待つ
; RxDに割り当てられているBit0を調べる
IN A,(0A2H) ; 11CLK [13CLK]
AND C ; 4CLK [ 5CLK]
JR NZ,WAIT_BIT ; 7CLK [ 8CLK]
; RTSをOFFにする。データを受信後にRTS OFFを送っても間に合わず、次のデータが送られてしまうのでここで
CALL RTSOFF ; [51CLK]
; portAから入力する
LD A,E ; 4CLK [ 5CLK]
OUT (0A0H),A ; 11CLK [13CLK]
; この時点で、122CLK経過しているので、最初のデータ読み取りタイミングに突入している。
; RxDに割り当てられているBit0からデータ読込み。
; 受信データはCregに組み立てられる
LOOP1:
IN A,(0A2H) ; 11CLK [13CLK]
RRA ; 4CLK [ 5CLK]
RR C ; 8CLK [10CLK]
CALL WAIT ; 17CLK [18CLK] / CALLしないで、ここにWAIT処理を書いてもいい
DJNZ LOOP1 ; 13CLK [14CLK]
; 受信データ確定
LD A,C
RET
;-------------------------------
; WAIT ルーチン
; CPU 3.9936MHzなので、3993600 / 38400 = 104clock
; ここがCALLされた時点で59CLKを消費
; PC-6001のM1ステートは常に+1Clockされます
; []内の数字がP6でのクロック数です
WAIT:
NEG ; 8CLK [10CLK]
NOP ; 4CLK [ 5CLK]
NOP ; 4CLK [ 5CLK]
NOP ; 4CLK [ 5CLK]
NOP ; 4CLK [ 5CLK]
NOP ; 4CLK [ 5CLK]
RET ; 10CLK [11CLK]
;-------------------------------
AYSET:
; AY3-8910入出力設定
; I/OportAを入力に
; I/OportBを出力に
LD A,07H
OUT (0A0H),A ; REG7
LD A,080H
OUT (0A1H),A
; 初期BIT状態(アイドル状態に->HIGH)
LD A,0FH
OUT (0A0H),A
LD A,7FH
OUT (0A1H),A
RET
;-------------------------------
; RTS信号はBit3に割り当てられている。
; ビット単位での状態変化は出来ないので、送信用TxDも変化してしまうことに注意
; RTS ON, TxD 0 --> 0000_0000
; RTS ON, TxD 1 --> 0111_0111
; ここでTxDをLOWにしてしまうとSTART BITとみなされてしまい、向こう側の機器で
; データの読み取りをしてしまうので、TxDは1にしておく事
RTSON:
LD A,0FH ; AY3-8910のREG15に77H(0111_0111)を出力
OUT (0A0H),A
LD A,77H
OUT (0A1H),A
RET
; RTS OFF, TxD 0 --> 0000_1000
; RTS OFF, TxD 1 --> 0111_1111
; AY3-8910のREG15に7FH(0111_1111)を出力
RTSOFF:
LD A,0FH ; [ 8CLK]
OUT (0A0H),A ; [13CLK]
LD A,7FH ; [ 8CLK]
OUT (0A1H),A ; [13CLK]
RET ; [11CLK]
実行アドレスの都合で、拡張ROM&RAMカートリッジが必要ですが、アドレスを変更すれば、RAM 16KByteの初代機でも可能です。
プログラム中のクロック計算ですが、PC-6001ではメモリアクセスやAY-3-8910への入出力でWAITがかかるので、補正しています。[]の数値がPC-6001でのクロック数です。
このコードをBASICから実行できるようにして、CLOADで読み込めるようにしたファイルを用意しました。これをCLOADで読込んでからRUNすると、テストプログラムが実行されます。
RUNした後、Acknowrichの通信ウィンドウ左下にあるCTSが点灯していれば通信OK(PC-6001側のデータ受け入れ準備OK)な状態ということになります。
Acknowrichの編集メニューから、BINARYモードを選択に切り替え、通信ウィンドウに00を入力してEnterを押すと、00HがPC-6001に送られます。続けて、01, 02 ... FFと順に入力(&Enter)していきます。
最後にPC-6001側でSUCCESSと表示されればテスト完了です。
順に打ち込むのは大変だと思いますので、こちらの00からFFが並んでいるだけのファイルをAcknowrichのメニューから編集→ファイル転送で送信すると、まとめて確認が出来ます。
正しいデータが受信できなかった場合、一行目には期待する値、2行目には受け取った値を表示してERROR表示になります。(下記の例では、05が送られてきて欲しいのに55Hを受け取った)
解説というより、上記プログラムの使い方です。
CALL AYSETをした後、割り込み禁止(DI)とBUSREQ OFF(LD A,02H / OUT (93H),A)を実行してから、CALL RECVを呼ぶと、1バイト受信されます。CALL RECV中、Z80は受信待機&受信データの構築に全力を出す必要があるため、割込み処理を受け付けることが出来ません。
ジョイスティック端子、AY-3-8910のポートA/B、PC-6001のIN命令で読み取るビットの位置は、上記のプログラムを参照してください。受信データ(RxD)は、PORT-Aのビット0、Z80からはI/OアドレスのA2HのBit0から読み取ることになります。
上記のプログラムは、8410Hから配置しています。PC-6001の32K RAMでは、BASICプログラムが8401Hから配置されていきます。また、これを実行するためのBASICプログラムが必要なので
10 EXEC &H8410
とだけ書かれたBASICプログラムの後に、上記のマシン語プログラムを8410Hに読み込まれるようにCLOAD出来るようにするため、簡単なバッチファイルを書きました。BASIC部分、マシン語部分、CLOAD終端検出用の00H9個というファイルを結合しています。 また、CLOAD可能なプログラムを、実機で読み込ませるためにはWAVファイル化する必要があるので、wavへの変換プログラムのp6towav.exeを使わせてもらっています。
上記のプログラムでは、38400bpsで速度を調整していますが、WAIT周りを調整することで57600bpsでの受信が出来ることは実験済みです。ただ、データの一部が化けることがありました。
更に上の115200bpsを目指そうとすると、ほんの少しだけZ80側の処理が間に合わず、最初の1bitか最後の1bitのいずれかが受信に失敗してしまいます。これについては、最初のBitを受信する前のRTSをOFFにする処理をなんとかするしかなく、そもそもRTS/CTSによるフロー制御を行うのをやめる、というのが一つの解決方法です。
RTS/CTSにるフロー制御をせず、115200bpsを実現する方法については、えすびさんがジョイスティックポートでRS-232C通信という記事を書かれていますので、参考にしていただくのがよいと思います。その場合、ハードウェアもシンプルに「ジョイジョイファイルシステム」のようなUSB変換器を使うことが出来ます。