ALTAIR 8800b PCBs

以下にALTAIR 8800bを構成する主要な基板をお見せします。
8800 busの基板のサイズは、幅254 mmでカードエッジコネクタを除く部品実装面の高さが127 mnと、たいへんに切りがよくできています。インチで表示すると10 inchと5 inchですから。カードエッジコネクタは3.175 mmピッチの100端子になっています。間隔の3.175 mmというのも、インチに直せば1/8 inchで、つまりはアメリカの製品なのですね。やはり。

Altair 8800b CPU board

これがCPUとクロックジェネレータやバスバッファなどが搭載された基板です。このCPUにはNational Semiconductor社製のINS8080ADが使われています。その左上にある金属の四角いものが水晶発振子で18.000 MHzが使われています。クロックジェネレータはCPUの直上に2個あるうちの左側のプラスチックパッケージのICで同じくNS社製のDP8224が使われています。クロック周波数は水晶発振子の周波数の1/9で2 MHzちょうどです。
電子部品を見慣れている人ならおわかりでしょうが、使用されている抵抗のサイズが必要以上に大きいですね。当時でも、たとえば国産のEMIC SI/Oボードを見ればわかりますが1/4 Wサイズの抵抗器が使われていました。ここで使用されているのは1/2 Wサイズではないかと思われる大きさで、デジタル回路に使用される抵抗器としては必要以上に大きめです。たとえば5 Vにプルアップしている2.2 kohmの抵抗の消費電力はせいぜい0.012 Wで1/16 Wの抵抗でも使用可能ですが、当時使用されていた抵抗は1/4 Wが普通で1/8 Wが特殊な小型用途という状況でしたから、1/4 Wを使うのが普通です。まさかアメリカ人一般の器用さに合わせて大きめの部品を使用したわけではないとは思いますが、でも、もしかしたらそうかもしれないなどと考えたくなってしまいます。
あと、プリント基板のパターンは手貼りなのですが、このCPU基板といい、下のC/Dインターフェース基板といい、パターンの引き回しが気持ち悪いねぇ。こちらの感覚ではイヤ。定規で線を引いてパターンを作りながら、ほかのパターンと当たりそうになると、その場でちょこちょこっと変更してなんとか接続しているという感じで、直線的なんだけど細かいところはいいかげんに曲がっていて、しかも曲がり方が美しくない。他のパターンとぶつかりそうだったから曲げて修正してあるけど、後でパターンを見直してぶつかるはずのパターンが取り去られた後でも、回避したパターンを直線に直しておこうなんてこともしてないし、多数の線が並行に走っているところで後の方で隙間がなくなってくると、その線だけ細く描いて納めようとしてるし。写真はJPEG圧縮で細かいところがつぶれているけど、線の太さが一部変になっているくらいはわかるかな。
電源ラインにフェライトビーズを挿入するのは悪い習慣ではないのですが、入れ方が誤っている場所があったりして、少々技術レベルに疑問を持ってしまいますね。まぁ、バスのGND端子が背中合わせの2端子しか存在しないというあたりから問題なんですけど。

Altair 8800b D/C interface board

これがCPUボードとコンソールパネルを結び付けるインターフェース基板です。
CPUボードも、この基板も、どちらも写真からはわかりませんが、かなり反っています。おまけに組み立てに使用されたフラックスの品質が悪くて塩素分が多かったためか、部品の足や半田に腐蝕が見られます。品質管理はちょっと不得意だったようで。あ、外部のところに書いたけど、このALTAIR 8800bは組み立てられたものを輸入したので、品質管理はすべてMITS社の側の責任ですから。
やはりフェライトビーズの挿入位置に問題があります。カードエッジコネクタの右端のそばにあるL3というフェライトビーズは、バスのGND端子とカード内のGND配線の間に入れられているのだけど、こうすると共通インピーダンスを高め高周波的なノイズマージンが下がって、良いことはひとつもありません。実質的に誤動作を導くほどの悪影響もないのだけど、結局は役に立たないフェライトビーズが入っているというだけで、コスト的観点からも無駄。

Altair 8800b display/control board

コンソールパネルのスイッチやLEDを取り付ける基板は、分解するのが手間なので、マニュアルの図をスキャンしてしまいました。単にスイッチやLEDとLEDの駆動回路くらいが搭載されているのではなく、Display/Controlボードという名称のようにコンソールパネルからの指令をCPUに実行させるための凝った回路が載っています。47個ものICが取り付けられていますからね。残りの2枚の基板を合わせたよりもICの個数が多いくらいです。
左上から2番目のICはUVEPROMの1702Aです。残りの24ピンのICは8212で、便利な8 bitラッチとして使われています。このコンソールパネルの動作は技アリで大変に興味深く、基本設計の悪さを指摘してきた私も誉めたくなるくらいの回路です。簡単に表現すると、1702Aの中にパネル回路を制御するマイクロプログラムとCPUへの命令が交互に書き込まれていて、パネル回路とCPUが協調してメモリの読み書きなどのコンソールパネル指令を実行しています。
あと、私の所有するロットでは、このDisplay/Controlボードに問題があって、長時間使用すると特定のICが破損します。なんと普通のLS TTL回路のプルアップ抵抗が5 Vに接続されずに8 Vの非安定電源に接続されている場所が1ヶ所あって、74LS04の入力がじきに破壊します。修正箇所はわかっていますから、製造番号の近い8800bを使用している方は連絡してください。

このALTAIR 8800bのようなコンソールパネルを持つ8080Aを使用したコンピュータを作ろうとすれば、普通はコンソールパネルからのメモリの読み書きにDMAを使用します。CPUをHALT状態にして、普段CPUボードが出力しているアドレスバスやコントロールバスなどをハイインピーダンスにしてCPUボードをバスから論理的に切り離してから、コンソールパネルのアドレススイッチの状態をアドレスバスに接続します。その上でメモリの読み出しの際にはコントロールバスに含まれるメモリからの読み込みストローブ信号を有効にして、その際にデータバスに出力されるメモリの内容をコンソールパネルのランプに表示します。メモリにデータを書き込む場合には、アドレスに加えてコンソールパネルのデータスイッチの状態をデータバスに出力しておいて、コントロールバスにメモリへの書き込みストローブ信号を出力します。
おっと、ALTAIR 8800bではアドレススイッチとデータスイッチが独立していませんでした。アドレスを内部に設定してから、同じスイッチで書き込みデータの指定もやっています。おまけに操作対象のアドレスをオートインクリメントする機能もありますね。このような機能を実装しようとすれば、74193のようなデータをセット可能なアップダウンバイナリカウンタをアドレスポインタに使用することでしょう。まずカウンタにスイッチの値をロードし、そのカウンタの値をアドレスバスに出力するようにします。あとのデータの読み書きの手法は前と同じです。アドレスの値はアップダウンカウンタに記録されていますから、パルスひとつで次のアドレスや前のアドレスに変化させられます。単純にアドレススイッチを使うよりは使い易そうですね。
ALTAIR 8800bも同じようなことをやっているのでしょうか。いや、回路図にはそんなカウンタが並んでいませんし、それでは8800bのようにRUNスイッチでアドレス表示のアドレスからプログラムの実行開始ができません。実はALTAIR 8800bはアドレスカウンタの代わりに8080A内部のプログラムカウンタを使用するという離れ業を行っています。CPUが命令をフェッチするときにREADY信号を操作して、あたかもメモリがおそろしく遅いように扱えば、CPUのメモリアクセスサイクルがずっと続きます。その間はアドレスバスにCPUのプログラムカウンタの値が出力されています。これがアドレスカウンタの代わりになります。同時に命令を読み出すためのメモリ読み込みストローブ信号も出され続けていますから、データバスにはメモリの内容が出力され続けていて、それをコンソールパネルに表示することができます。
EX NEXT機能はCPUにNOP命令を読み込ませるだけで実現できます。NOP命令なら、プログラムカウンタ以外のCPUの内部状態を変化させずに、プログラムカウンタの内容がインクリメントされるためです。8800b busと8080Aの間にある双方向バッファをハイインピーダンスにして外部バスと8080Aを切り離し、8080Aのデータバスに直接NOP命令のオペコードをパネルの制御回路から出力して、外部バスとは無関係にCPUにNOP命令を強制実行させます。そして、元と同じ状態になれば、次のアドレスのメモリ内容が表示されることになります。EXAMINE機能はどうするかといえば、JMP命令を読み込ませることで実現しています。JMP命令は3 Byte命令ですが、2 Byte目にはコンソールパネルのスイッチの下位バイト相当の値を、3 Byte目には同じく上位バイト相当のスイッチの値を読み込ませます。すると、プログラムカウンタにパネルスイッチの値をロードしたことになります。
DEPOSIT機能はメモリの読み出しストローブの出力を禁止してスイッチの内容をデータバスに出力すると同時にパネルの制御回路から書き込みストローブ信号をパルス出力することで実現できます。DEP NEXT機能はCPUにNOP命令を読み込ませてからDEPOSITと同じことを行います。
RUNやSINGLE STEPやSLOW実行などに関しては、CPUのWAIT条件を適切に操作するだけで実現できます。プログラムカウンタとアドレス表示が一致しているわけですから、単にWAITをはずしてメモリからのデータをフェッチできるようにすれば、表示されているアドレスから実行を開始できます。その直後に強制的にWAIT状態にしてしまえば、ステップ実行です。WAIT解除と強制WAITを定期的に行えば、SLOW実行になります。
残りのパネル操作のアキュムレータ操作関係は大技の力技が必要です。特定の命令列をCPUに入力すれば、アキュムレータの内容をデータバスに出力したり、入出力命令を実行することができます。ただし、そんなことをしてはプログラムカウンタがいくつも変化してしまいます。そのため、表示しているアドレスデータ、つまりプログラムカウンタの内容を2個の8212にラッチしておき、読み込ませる命令列の最後でJMP命令のオペコード、以前のプログラムカウンタの下位アドレスを保持している8212のデータ、同じく下位アドレスを保持している8212のデータの順でCPUに読み込ませます。これでコマンドを実行する前の状態にプログラムカウンタを復帰できるというわけです。
これらのシーケンスを実現するのは、簡単そうに書いてしまいましたが、特定の命令をCPUである8080Aのデータバスに出力すると同時にバスに接続された各種バッファを制御しつつコントロールバスに適切なストローブパルスを出力したり、パネルスイッチの内容をデータバスに出力して同様のバッファやバス制御を行ったり、結構複雑なシーケンス制御を続けて行う必要があります。そのための制御にマイクロプログラム方式を利用しています。ROMの1702Aには、偶数アドレスにマイクロプログラムが、奇数アドレスにCPUに読み込ませる命令コードが、書き込まれています。マイクロプログラムのあるビットが1なら奇数アドレスの命令コードをデータバスに出力してCPUに読み込ませるとか、別のビットが1ならパネルスイッチの下位バイト相当をデータバスに出力してCPUに読み込ませるとか、また別のビットでメモリへの書き込みストローブパルスを生成するとか、8 bitのデータのそれぞれが別の意味を持たされています。そうして、バス制御などの複雑なシーケンス操作を単純化しているわけです。パネルのコマンドスイッチを操作すると、そのコマンドに応じて1702Aに与える上位4 bitのアドレスが決定され、同時に下位4 bitのアドレスを与えるべきカウンタがリセットされます。内部クロック信号によって下位4 bitのアドレスが順次インクリメントされながら、ROMに納められたシーケンス列が実行されています。ROMにはシーケンスの末尾を表すデータも格納されていて、そのビットパターンが検出されるまで、シーケンスが連続実行されているという仕組みになっています。
なお、RUN, STOP, SINGLE STEP, SLOWのコマンドに関しては、ROMを使用せずにCPUに与えるREADY信号をコントロールしているシングルステップ制御回路だけで実現しています。このシングルステップ制御回路は、他のコマンドを実行するときにはもちろん1702Aの中のマイクロプログラムによって制御されます。
これがALTAIR 8800bのコンソールパネル制御の概要です。
 

8800 busの仕様を以下に整理してみます。まずはバスの信号配列の表です。

番号 記号      意味                    番号 記号       意味
 1  +8V        +8 V unregulated         51  +8V        +8 V unregulated
 2  +18V       +18 V unregulated        52  -18V       -18 V unregulated
 3  XRDY       External Ready           53  SSWI*      Sense Switch Input
 4  VI0        Vectored Interrupt #0    54  EXT CLR*   External Clear
 5  VI1        Vectored Interrupt #1    55  RTC      $ Real Time Clock
 6  VI2        Vectored Interrupt #2    56  STSTB*   $ Status Strobe
 7  VI3        Vectored Interrupt #3    57  DIG1     $ Data Input Gate #1
 8  VI4        Vectored Interrupt #4    58  FRDY     $ Front Panel Ready
 9  VI5        Vectored Interrupt #5    59
10  VI6        Vectored Interrupt #6    60
11  VI7        Vectored Interrupt #7    61
12  XRDY2    $ External Ready #2        62
13                                      63
14                                      64
15                                      65
16                                      66
17                                      67
18  STAT DSB*  Status disable           68  MWRITE     Memory Write
19  C/C DSB*   Command/Control disable  69  PS*        Protect Status
20  UNPROT     Unprotect                70  PROT       Protect
21  SS         Single Step              71  RUN        Run
22  ADD DSB*   Address disable          72  PRDY       Processor Ready
23  DO DSB*    Data Out disable         73  PINT*      Interrupt Request
24  CK2        Phase 2 clock            74  PHOLD*     HOLD
25  CK1        Phase 1 clock            75  PRESET*    RESET
26  PHLDA      Hold Acknowledge         76  PSYNC      SYNC
27  PWAIT      WAIT                     77  PWR*       Write
28  PINTE      Interrupt Enable         78  PDBIN      Data Bus IN
29  A5         Address Line #5          79  A0         Address Line #0
30  A4         Address Line #4          80  A1         Address Line #1
31  A3         Address Line #3          81  A2         Address Line #2
32  A15        Address Line #15         82  A6         Address Line #6
33  A12        Address Line #12         83  A7         Address Line #7
34  A9         Address Line #9          84  A8         Address Line #8
35  DO1        Data Out Line #1         85  A13        Address Line #13
36  DO0        Data Out Line #0         86  A14        Address Line #14
37  A10        Address Line #10         87  A11        Address Line #11
38  DO4        Data Out Line #4         88  DO2        Data Out Line #2
39  DO5        Data Out Line #5         89  DO3        Data Out Line #3
40  DO6        Data Out Line #6         90  DO7        Data Out Line #7
41  DI2        Data In Line #2          91  DI4        Data In Line #4
42  DI3        Data In Line #3          92  DI5        Data In Line #5
43  DI7        Data In Line #7          93  DI6        Data In Line #6
44  SM1        Machine Cycle 1          94  DI1        Data In Line #1
45  SOUT       Output                   95  DI0        Data In Line #0
46  SINP       Input                    96  SINTA      Interrupt Acknowledge
47  SMEMR      Memory Read              97  SWO*       Write Out
48  SHLTA      HALT Acknowledge         98  SSTACK     Stack
49  CLOCK*     Clock (Inverted CK2)     99  POC*       Power On Clear
50  GND        Ground                  100  GND        Ground
端子1から端子50までが部品面の左から右へ並んでいて、端子1の裏にあたるハンダ面側に端子51が、端子50の裏面に端子100が並んでいます。意味の2文字前に$マークが付けられている信号は、8800bで新設された端子で、ALTAIR 8800aなどにはありません。記号が記入されていない端子は未使用です。
A0からA15までがアドレスバスで、8080Aの端子がバッファリングされて出力されています。CPUボードのアドレスバス出力を禁止するのがADD DSB*信号で、この信号がLになると他の信号や回路の状態とは無関係にCPUボードのアドレスバス出力がハイインピーダンスになります。
データバスは双方向バスでなく、入力と出力が別れた単方向バスになっています。これは、ALTAIR 8800開発当時に双方向性バスバッファの安くて使いやすいICがなかったのと、メモリボードに使用されると思われた2102というメモリLSIが入出力分離で単方向バスに接続するのも容易だったからだということです。まぁ、当時入手できる部品で安価に済まそうとしたわけですね。DO0からDO7までがCPUボードから見て出力で、メモリやI/Oへの書き込みに使われます。DI0からDI7までがCPUボードから見て入力で、メモリやI/Oからの読み込みに使われます。このような単方向バスを採用したため、以後に高度なDMA転送を利用した基板を設計する際に手間が増えることになりますし、双方向バスを使用しているマイクロプロセッサ周辺入出力LSIを接続する際にも部品が増えてしまうことになります。初期の設計時には周辺入出力LSIなんて存在しなかったので、しかたないとも言えるんですが。DO0からDO7のCPUボードの出力を禁止する信号がDO DSB*で、ADD DSB*と同じく周囲の信号や回路の状態とは無関係にデータバス出力をハイインピーダンスにします。
記号で先頭にPが付いているのはマイクロプロセッサの端子に直接対応する信号です。PINT*とPHOLD*が入力で、PWR*, PDBIN, PWAIT, PSYNC, PHLDA, PINTEが出力です。この6本の出力を切り離すのがCC DSB*信号となっています。例によって他の信号とは無関係にコントロールラインの出力をハイインピーダンスにしてしまうので、下手な制御はできません。ところで、よく見るとDMAの際にCC DSB*や他の出力禁止端子の制御に使うべきPHLDAまでCC DSB*でハイインピーダンスになってしまいます。CPUがバス操作を止めて別回路にバスを明け渡しているという意味の信号だから、各種バスバッファもこれに合わせてハイインピーダンスにすべきなんですけど。幸い、PHLDAは正論理でプルアップしておけばハイインピーダンスになってもHレベルと他の回路から認識されるので、PHLDAがHになってからCC DSB*を有効にしてハイインピーダンスにしてもなんとかなるんですけど。ちょっと回路がややこしくなってやだかな。しかも偶発的にCC DSB*が有効になると、他の回路がPHLDAが出力されて正規にCPUにDMA許可を取ったのだと認識してしまうのも、偶発的にそんなことになるなんて故障しているか回路設計の誤りだという点を差し引いても、やな感じです。PINT*は本物の割り込み入力です。VI0 - VI7はオプションの基板でPINT*やSINTAを用いて実装されるもので、標準のALTAIR 8800bでは使用できません。
記号で先頭にSが付いているSMEMR, SINP, SM1, SOUT, SHLTA, SSTACK, SWO*, SINTAの8本の信号はCPUが出力するステータス情報出力です。この信号を用いてメモリやI/Oの制御をすることが期待されますが、これを使用せずにメモリやI/Oボードの中でDO0 - DO7の情報をSTSTB*でラッチして同じ信号を得ることもできてしまうのが8800 busの問題点です。SMEMRやSOUTなどを使ってメモリやI/Oアクセスを制御するなら、Z80 CPUなど別種類のCPUを用いたシステムを構築できますが、データバスに出力されるステータス情報をSTSTB*でラッチするのを別種類のCPUで模擬する回路を設計しても、その送出時間の分だけ性能が落ちてしまうし、実現できないかもしれません。これらの信号出力を禁止するのがSTAT DSB*信号ですが、これも例によって他の信号や回路の状態とは無関係にステータス出力をハイインピーダンスにするので注意が必要です。
リセット信号にはPOC*, PRESET*, EXT CLR*の3種類の信号があります。POC*は電源投入時のオートリセット信号で、PRESET*は8080Aをリセットする信号、EXT CLR*は8080Aには無関係にI/Oデバイスのクリアに使用するということです。まぁ、I/Oデバイスではすべてのリセット信号のORを使ってリセットすればよいのでしょう。POCはCPUボード、PRESET*とEXT CLR*信号はD/Cインターフェースボードで駆動しています。オープンコレクタ出力ではないので、他の基板からは出力することはできません。
CPUにWAITサイクルを要求する信号はリセット以上に数が多く、XRDY, XRDY2, PRDY, FRDYの4端子があります。CPUボード内でただちに4入力NAND回路に接続されて、どれか1本でもLならWAITが入るようになっているという点で、同等です。しかし、FRDYはD/Cインターフェースボードが占有していて、パネル操作のために駆動しています。
SSWI*はI/Oアドレス0FFHをCPUが読み込んだとき、その他パネル操作の都合でCPUのデータ入力を使用するときに有効となりますが、CPUボードでも使用していないし、特に別回路で使用することもないでしょう。RTCは60 Hzのリアルタイムクロック信号が出力されているはずの端子ですが、これはオプションのReal Time Clock/Vectored Interrupt Boardがないと未使用端子でしかありません。STSTB*はステータス情報がデータバスに出力されるタイミングを表す信号ですが、前述のように互換性のためには使用すべきでない信号です。DIG1はフロントパネルからの制御のためにCPUボードに与えるべき信号で、他のボード類には無縁です。
MWRITEはメモリへの書き込みタイミングで、メモリボードではこの信号を使用しないといけません。PWR*やステータス情報から同じ信号を作成できますが、8800bのフロントパネルからのデータの書き込み時にはPWR*やステータス情報が正しく変化せず、MWRITEだけが出力されるためです。しかし、初期のTDL社のZPU(Cromemco社にあらず)やIMSAIのCPUボードはMWRITEを正しく作成せず、トラブルの元でした。
UNPROT, PROT, PS*信号はメモリの書き込み保護に関する信号で、対応メモリボードでないと使えません。簡単にいえば、メモリボードにはバンクごと(1 KByteとか4 KByte単位のメモリブロック)にメモリの書き込み保護フリップフロップ(FF)があり、コンソールパネルから特定のメモリアドレスを参照しているときにUNPROT信号が有効になれば、そのメモリアドレスを含むバンクの書き込み保護FFがクリアされます。逆に同じ状態でPROT信号が有効になれば、そのメモリアドレスを含むバンクの書き込み保護FFがセットされます。書き込み保護FFがセットされていると、MWRITE信号は無視されて書き込みが行えず、読み出しだけが行えるROMのようになります。これでプログラムの暴走や誤操作で書き換えたくないメモリ領域を保護できるわけです。これだけでは、あるメモリバンクがプロテクト状態かどうかわかりませんから、その表示のために存在する信号がPS*信号です。特定のメモリアドレスが参照されているとき、そのアドレスを含むバンクの書き込み保護FFの状態がPS*信号に出力されます。フロントパネルでは、PS*信号に応じてパネル面のPROTECT LEDを点灯させますから、書き込み保護FFの状態を知ることができます。
SSとRUNはフロントパネルの内部状態を表す信号ですが、特に意味のある使用法があるわけでもありません。CK1, CK2, CLOCK*は2 MHzのクロック信号です。一定周期のクロック信号が必要な場合には、CLOCK*信号を使うとよいでしょう。この信号はIEEE-696でも2 MHzクロック出力が保証されていますから。

バスの信号を観察するだけでも、ある種のでたらめさが読み取れると思います。アドレスバスとデータバスと合わせて、配列順序の規則性がみられません。CPUボードのパターンを作成するとき、配線しやすい順序だったのだろうとしか思えませんね。FRDY端子やDIG1信号のように、CPUボードとD/Cインターフェースボードの間でだけ意味のあるものまでバスに出ています。これらの基板間にさらに別のコネクタで配線するのを避けているだけのようです。VI0からVI7までのベクトル付き割り込み信号やRTC信号がサポートされていれば立派ですが、じつはこれらはオプションの制御基板を取り付けなければ使用できません。定義だけです。制御信号には正論理と負論理が入り交じっていて、問題になりそうです。
最大の問題点はグラウンドや電源回りで、GND端子が2本しかないというのは困ったことです。高速の信号伝送にはストローブ系の信号の隣にGND端子があった方が有利ですし、2端子だけでは少し消費電流の大きい基板では端子の直流抵抗による電圧降下によって他の基板とのGND電圧の関係が変化してしまい、0.4 VしかないTTL信号のノイズマージンがほとんどなくなってしまいます。
もうちょっと良く考えて設計しろよ、と、言いたくなってしまいますが、そもそもは1機種限りの低価格コンピュータキットのつもりで設計したはずで、何十社から多数の製品が発表され全世界で使われることになる標準バス規格の原形を設計しているつもりはまったくなかったでしょうから、お門違いの文句ではあるでしょうね。
ただ、これがアメリカを中心に一時代を築いたパーソナルコンピュータバスアーキテクチャの原形なんです。はい。

Return to IC Collection