SBC80系 シリアル入力の2系統対応(1)

SBC8085やわたしのKZ80-CPUBでシリアルを2系統にしてみようと思い立った記録です。その(1)は割り込みコントロール部分をロジックICで組んでみたパターンです。

発端

発端は、tomi9さんのAKI80PlusCFボードを頂いて作成したことから始まります。AKI80PlusCFボードは秋月電子で販売されているZ80互換CPUボードでZ80 CPU+CTC+SIOなどなどを搭載している豪奢な構成のボードです

このボード Z80 SIO/2相当が入っているため、なんとシリアルA/Bを装備なのです。Grant氏がCP/Mを動かした構成もSIOなので2シリアル。Grant氏の機械語モニターも、CP/M用BIOSも もともとは2シリアル対応となっています。
これはちょっと憧れる構成でした。幸い手元にKZ80-IOB(I/Oボード)のプリント基板も予備がありまして、シリアルLSI 8251×2つの構成にしたら同じように2シリアルにできるのではと思いつきました

割り込みコントローラの回路

もともといままでのKZ80-IOBやSBC8080 SUBルーズキットは割り込みをかけてくるのは8251のみだったため、複数の割り込みをコントロールしていませんでした。80系のCPUは割り込みがかかった際(#INT信号がきたら) データバスから命令を読み込む仕様となっています。割り込み時には周辺チップ側で、RSTxx命令やCall命令を発生させることで割り込みルーチンへジャンプする動きとなります。

ちなみにSBC8085、KZ80-CPUBはデータバスをプルアップしていまして、割り込みがかかったのち データバスに 16進数でいうとFFh、80系のインストラクションでいうと RST 7 (RST 38h)が発生したように挙動するようになっています。つまりシリアル割り込みがかかると 38h番地へのCallが発生して割り込み処理ルーチンが走りシリアル入力の文字をリングバッファへ保存する動きとなっています。
(SBC8080 CPUルーズキットだと8228の#INTAが+12Vにプルアップされていて同様の挙動をするようになっています。….と「古典電脳伝説」で読みました^^)>)

今回は8251×2つで2シリアル対応にしたいので、複数の8251の割り込み信号(シリアルだと「データが1バイト届いたよ」という信号)をうまいことデータバスに「命令」として乗せてあげるコントロール回路が必要となります。いろんな参考書にこの動作をする回路が出ていまして、それを参考に作ってみた回路図が以下のものです。
シリアルAからの割り込みの場合は RST 7(RST 38h)、シリアルBからの割り込みの場合はRST 6 (RST 30h)を発生させる回路です

74HC148はプライオリティエンコーダーというロジックICで、Lレベルとなった入力端子にあわせて3bitの出力を出してくれます。入力端子7番が一番プライオリティが高く、入力端子0番が一番低くなっていて、プライオリティの高い番号がバイナリ3bitで出力されます。また割り込み信号がどこかの入力端子に届いたときにEO端子がHレベルになりますので、CPUへのINT信号として使用します。
80系のCPUのRST命令を2進数でみると以下のようになっています。上位2bit、最下位3bitが 1 になっていて、真ん中の3bitが 0〜7に変化しています。この3bit分をデータバスへ出力してあげればRST命令になります。

ニーモニック命令コード(2進数)Callアドレス
RST 0 (RST 00h)1100011100h
RST 1 (RST 08h)1100111108h
RST 2 (RST 10h)1101011110h
RST 3 (RST 18h)1101111118h
RST 4 (RST 20h)1110011120h
RST 5 (RST 28h)1110111128h
RST 6 (RST 30h)1111011130h
RST 7 (RST 38h)1111111138h

74HC148プライオリティエンコーダーの出力は負論理(Lレベルが 1 )なので74HC04 NOTゲートで反転させます。それを74HC541 スリーステートバッファへ入れます。74HC541 スリーステートバッファの入力端子をすべてプルアップしているためプライオリティエンコーダーの出力がつながっていない端子は H つまり “1” となります。
ただ、いつでもデータバスにRST命令を流していると他のLSIの出力とぶつかるため、CPUからの#INTA(割り込み受付)をトリガーにしてRST命令を流すようにします。

ちなみに、KZ80-CPUBはSBC8085ルーズキットのように#INTA(割り込み受付)信号を出していませんでしたので、上記のように#M1(マシンサイクル1)信号と#IOREQ(I/O要求)信号のORをとって出力するように細工しました。Z80の場合は割り込みを受け付けるとその2つの信号線がLレベルになるのです。

試作してみた

上記の回路でユニバーサル基板を作成し、KZ80-IOB x2枚を使って試作してみました。KZ80-IOBの割り込み信号はパターンカットして、SBC8080バスとは別経路でユニバーサル基板へつなぐ作戦です。

CPUボードの方は、SBC8085ルーズキットはそのまま使えますが、KZ80-CPUBは#INTA(割り込み受付)信号をつくる必要がありますので、基板裏にSOPの74HC32をはりつけて配線してみました。

Grant’s機械語モニター、CP/Mの対応箇所

いままではハードウェア対応の話でしたが…..
2シリアル対応にするために、Grant’s機械語モニターとCP/Mに2シリアル対応を入れる必要があります。基本的には以前の移植手順のシリアル部分を2シリアル対応に戻すことになります。
8251×1(シリアルA)対応したルーチンをコピペしてシリアルB用ルーチンを作成します。(きっともっと良い書き方があるはずですが…..ちょっと今回は手抜き)

機械語モニターの対応箇所

  • 割り込みシリアル入力処理は 従来のアドレス38hからジャンプした先のルーチンはシリアルA用、アドレス30hからジャンプする先にはシリアルAの割り込み入力処理をCOPYしてシリアルB用にします。(データ保存バッファとしてリングバッファも2つ準備します)
  • INIT(初期化)処理でどちらかのシリアルからスペースバー入力されたらそちらを主シリアルと判断するルーチンを復活させます。ここで、primaryIOというワークエリアにシリアルAなら00h、シリアルBなら01hをセットします。
  • conin(シリアル入力)、conout(シリアル出力)、CKINCHAR(入力文字チェック)はprimaryIOに 00hが入っていたらシリアルAの処理、01hが入っていたらシリアルBの処理を実行するようにします。

CP/Mの対応箇所

CP/Mは従来同様 BIOSのシリアル入力部分を対応します。

  • 機械語モニター同様にserialInt(割り込み受信)、const(シリアル状況)、conin(シリアル入力)、conout(シリアル出力)の各ルーチンを2シリアル分用意します。
  • popAndRunルーチンで機械語モニターからのCP/M起動時にAレジスタで渡ってくるprimaryIOの情報(00h/01h)をもとにCP/MのIOByteを設定するルーチンを復活させます。
  • gocpmルーチンで 38hにシリアルA用割り込み処理のジャンプ命令をセットしていますので、それを真似て30hにシリアルB用割り込み処理へのジャンプ命令をセットします。

稼働確認

ハードウェアとソフトウェアの準備ができたら、稼働確認です。

Tweetをたどっていただけるとわかりますが、実はすんなりとは行かなくて(当初の回路図は考慮漏れだらけだったり….)ハマりましたが当初の予定どおり、機械語モニター起動時にシリアルAかBを選択(スペースバーを押したほうが使われます)後、CP/Mがどちらのシリアルポートでも稼働しました。

i8080/8085用に移植したGrant’s機械語モニターをさらに2シリアル対応したため、メモリーの予備エリアを食いつぶしてしまいました。もっと良いコードに今後修正していけたらと思っています。

広告