マイコンの製作(自作CPU 8080)
(74HC(LSもある)シリーズのDIPで8080もどきを製作。名称をMDK8080とした。)
2016年11月
1. はじまり
プロファイルのところでマイコンのことを書いたので思い出したが、Altair8800のようなコンピュータを作ろうとした作りかけあったはずと押入れを探してみた。でも見つからなかった。どうしたのかなあ。?!そうだ、現在のところに引っ越した時に、ガラクタ廃棄命令で廃棄したかもしれない。しまった。捨てなければよかった・・・・。
懐かしくなりネットで8080を検索すると、あるある、みなさん8080もどきを製作してCP/Mまで移植しているようだ。そのなかでも中日電工さんのページが圧巻だった。なんとTTL(実際は74HC)で8080CPUを作ると言うのである。記事を読んでいるうちに作りたくなった。出来たとして何に使うか、何につかえるか?などと思ったが、そんなことを考えると趣味なんてできない。これはロマンである。でも組み立てるだけではつまらない(天邪鬼だねぇ)。組み立てるのではなく創るのである。自分で回路を考えて動かすのが楽しいのである。
2016年12月
2. 回路設計
自分で回路を考えようと意気込んでみたものの、はたして回路ができるのか。まずはCPUの仕様を探した。98-153B_Intel_8080_Microcomputer_Systems_Users_Manual_197509と言う青い表紙の資料がダウンロードできた。便利な世の中だ。
でもALUが手に入るのか?、中日電工さんは加算器を使っていたが。ALUの74HC181を探すと中国にあった。とりあえず注文だけしておいた。ALUが入手できるつもりで回路を考えることにした。
8080の命令は16進数で表現されているが、レジスタは7個+1なので、オペランドは3bitである。これはPDP−11と同じように3bitで区切った方が分かりやすい。命令デコードは3bitで区切ってデコードすようにする。
MEMORYのREAD、WRITEとIOは分離して出すようにする。つまり8080+8224+8228が一体になった回路とする。
約1ヵ月かかって回路が出来た。頭の中では動作している(いつもそうだが、現実は違う・・・汗)。でもALUが届かない。1ヵ月経つのだが。問い合わせたら、途中で紛失したようなので再度送ると連絡が来た。さすが中華・・・・。もう1ヵ月待たねば。
回路図 ___
でもどうやって基板へつけるか?。秋月にユニバーサル基板のA4(よりちょっと大きい)サイズがあるのが分かった。これに載らなければあきらめよう。図面を描いてみた。
おやおやうまく載ってしまった。少し余裕がある。あと2〜3個ICを載せれる。回路デバッグでICが追加になっても何とかなりそうだ。つまり作れという天の声か・・・・。
ちなみに赤がアドレスレジスタ。黄緑がプログラムカウンタやスタックポインタ、HLなどのレジスタ部分である。緑はAレジスタやフラグレジスタ、ALU、シフト用レジスタなど、ピンクはメモリーREAD、WRITE、IO READ、WRITEなどの信号部、青が命令レジスタ、水色がクロックと命令デコード部、黄色が命令実行部である。
ALU周りの回路を考えるときに、ALUの仕様を検討したが、データは負論理で設計されている。しかし、そのままの動作で正論理で受け取ることもできる。74HC181は論理を切り替えて加算、減算、AND、OR、XORなどそのほかのロジックも動作する。その他のロジックのときに正論理の動作もできるようだ。しかし、内部等価回路を見るとA=Bの信号は負論理でないとうまく動作しないように見える。説明書には正論理の場合どうなるか明記されていない。事前に調べたいが、中華からはまだ届かない。ひょっとすると永久に届かないかもしれない。事前に調べたいのと保険にと別途探すことにしたが、やはり無いようである。無いというのは間違いであるところにはあるが、100個売りで1個売りはしていない。100個もいらいないのでそこはダメである。では、74LS181はと調べると、これはまだ残っているようで、2個ほど購入した。最悪ALUだけ74LS181にすることにする。
さっそくALUの実験をやってみた。やっぱりA=Bは負論理のときだけ正しく動作する。なので負論理で回路を設計した。
2017年1月
発注していたIC(一部)がaitendoから届いた。
aitendoさん、お願いですからICは導電スポンジにさして下さい。
2017年1月
残りのICがchip1stopから届いた。梱包はさすが、導電スポンジやIC用レールに入っている。
圧巻はこれかな。74HC04が200個である。200個以上での販売だった。でもこれで131円である。在庫処分かな?
2017年1月
今日何気に回路をみているとDAAの計算回路を間違っているのに気付いた。なんで間違ったかなぁ。ALU回りを正論理から負論理回路に変更したときにもれたかなぁ。ICがそろったし(コネクタ類はまだだが)。そろそろ作りはじめるかな。どのくらい掛かるだろう。20PINと16Pと14Pだが20Pが多い。おおざっぱに20Pが200個として4000本の配線かな。
えっ・・・。そういう計算では無いって・・・。そうだけど・・・。ICのピン3本を繋ぐ配線は2本の計算だからですね。でもコンデンサやプルアップ抵抗やらを繋ぐのでそれを含めて、おおざっぱに計算しているのです。
4000本だとすると40本/日とすると100日かかる。3ヵ月ほどかかるかなぁ。すると5月の連休にテスト開始できるかな?
では、それを目標にがんばろう!
2017年2月
最終チェックと思ってなにげに回路図をみていると、IC番号にダブりがあった。やれやれ、ICを1個追加だ。おやーー、番号に空きがある。どうやらコピー後の変更忘れか?。番号を取っているので変更忘れはなさそうだが・・・はて?。いずれにしろ配置図を修正せねば。おや、配置図にも間違いが・・・。コピーして配置して番号を書き換えるの忘れている。やれやれ恥ずかしい配置図をアップしてしまった。
修正した配置図
2017年2月
ああ、そうそう。回路設計するにあたり、本棚の肥やしになっていたこの本を引っ張りだして参考にした。約40年前にCPUを作ろうとして買った本である。仕事でコンピュータをさわっていたせいもあるかもしれないが、結局完成しなかった。Profileに書いたが、TMS8080を使った部品キットを作っただけで頓挫していたのだ。40年経ってようやく作ることになろうとは。
2017年2月
ICを少し取り付けてみた。配線はまだこれからである。40本/日はちょっと辛いなあ(弱気・・・)。
それと名前を付けてみた。
MDK8080とした。8080もどきである(笑)。
2017年2月
先日ICがそろったと書いたが74HC181はまだ届かない。今日、返金要求をしておいた。
ALUは74LS181を使うことにする。LSをHCで受けるにはプルアップが必要だ。HCTタイプだと受けることができるが、HCしか買っていない。
ちなみに74LS181の出力はこのようになっている。これではどう頑張っても3.6V以上は出てこない。
2017年2月
すこし配線してみた。まだまだ先は長い・・・・。
BUS以外の配線半ば、うーん、40本/日はやっぱり厳しいなぁ・・・。完成は遠いぞぉ・・・・。まあ、それだけ長く楽しめるということだが(そう思おう)、他のことが出来ない。
仕方ないけど。
2017年2月
ようやくBUSの配線が終わった。
ALU周りを実装した。
2017年2月末日
74HC181の返金手続きが完了して、返金されたことを確認した。(やれやれ)。
なのでALUは74LS181である。てか、もう実装してあるが。
2017年3月中
ようやくALU回りの配線がほぼ完了した。
2017年3月中
クロックと命令デコーダ部を実装した(配線はこれから)。
2017年3月中
奇しくもタイムリーに(?)こんな本が発売された。さっそく購入してみた。出版社から直接買えるので購入した。直接購入するとオマケのCDが付いていて本のPDFやソフトのソースファイルが入っている。これはお薦めだ。
「インテル8080伝説」の本。光の具合が悪く白っぽくなってしまった。
2017年3月末
だいぶ配線ができてきたが、まだまだだ。
しかし、ここまで配線してICのダブりが判明した。うーーーんん。このICが無いとHOLDを受け付けない。よし、HOLD無しだ!。あっ!・・・待てよ。HOLDができないとDEBUG回路が使えない。
仕方ない1個追加だ(やれやれ)。
黒いボックスコネクタと白いコネクタの間に1個追加した。
2017年4月中
ようやく配線ができた。と言っても命令実行部はまだだが。
ここまで出来ると命令フェッチとデコードが動作する(はず)。まあ、実行部が無いので全てNOPだが(笑)。
いや、実行部の不要なNOPは動くはずだ、他にもSTC,CMC(訂正:CMCは命令実行部があった)、HALTが動作するはずだが。
それを確認するためのDEBUG回路ボードを作らねば。
2017年4月末
DEBUGボードである。
まだ完成では無い。部品を付けただけである。プリント基板なら完成だが・・・。裏の配線はこれからである。
MDK8080の方は命令実行部が無いので、およそ半分のICしか搭載していない。もう直ぐGWだが当初の予定の半分しかICが付いていないので、40本/日はやっぱり無理だった。半分の20本/日ってところだ。
GWにDEBUG回路が完成すれば御の字だ。それからDEBUGしながら命令実行部を載せていくと、盆休み前に完成かな。まあそんなところだろう。
2017年5月中
GWではDEBUG回路の配線は終わらなかった。なかばにようやく完成した。ではDEBUG回路のDEBUGする回路を・・・・・な訳にはいかない。
取り敢えずCPUボードに接続して見た。
右端のLED群はレジスタを読み出して表示する。読み出すのはH8マイコンだ。CPUにHOLDを掛けて動作を停止し、DEBUG用のポートからレジスタの内容を読み出す仕掛けだ。
今表示しているのは読み出したつもりの適当な値だ。実際にうまく読み出すかはこれからである。
2017年5月末
H8ソフトのバグが少しあったが、DEBUG回路も何とか動作するようになった。DEBUG回路が動作するようになって、CPU回路のハンダ不良が5カ所あるのを発見した。
ハンダ不良を嘆くべきか、DEBUG回路がうまく動作したのを喜ぶべきか・・・・。
先にも書いたが、命令実行部のICが無くても実行できる命令の動作確認をした。
まずNOP命令。まあ、全て(上記命令以外)動作はNOPだが。動作する(当たり前??)。おそらく回路に間違いがあっても次へ進むのでよくわからんが。
次にSTCだ。STCもうまく動作した。次はEIだ。INT ENABLEをセットするだけなので、簡単に動作した。次はDIだ。さっきのENABLEを落とすだけ。これもうまく動作した。
さて残るはHALTだ。HALT命令で実行が停止した。停止したと言ってもINT ENABLEにしているとINTERRUPTを受け付けなければならない。とりあえず巧くいった。ただし命令実行部がないのでRST命令が実行できない。NOPとなって次へ進む。今の段階ではOKだ。
ここまでうまく動作したので、気をよくして命令実行部を実装する。
2017年6月初
LXI命令とDAD命令が実装できた。早速テストしてみる。
LXI B、4455H
LXI D、88AAH
LXI H、0CC33H
LXI SP、0F00FH
とパターンがダブらないようにデータを入れる。
レジスタの内容は読み出してLEDを点灯させている。うむうむ、うまくいったぞ。
DIPSWの一番下はHALT命令だ。突っ走らないようにHALT命令を置いている。
さて、DAD命令のテストだ。LXI命令が無いとレジスタにデータ設定ができないので、LXIが動作してからのテストだ。
DAD B
DAD D
DAD H
DAD SP
を試してみる。これはALUを使って、LレジスタはADD命令、HレジスタにはADC命令でそれぞれのレジスタを足し込む。
まずはうまく桁上がりするかどうか。
LXI H、00001H
LXI B、0FFFFH
DAD B
を実行。桁上がりしてHLレジスタは0となりCフラグはONしている。DAD命令で変化するのはCだけだが、テストの為全てのフラグをセットしている。
ACがON、ZがONしている。おや〜、SもONしている。0だからZがONして正解だが、SがONするのはおかしい??
回路図を調べたら、何と!間違っている。負論理にしたときに、変えなければならないをそのままにしている。やれやれ。
接続を変更だ。配線を追っかけようと、SのラッチICを見ると。な、っな、なんと、配線が無い!!。いや〜、歳のせいかな。回路を間違っていたうえ配線していないとは!
ミスのミスでミスの2乗である(とほほ)。そのおかげで(?)配線変更が楽だ(なんてね・・・)。
配線を追加して、動作OKとなった。その後、DAD命令でCフラグだけ変化するように配線を変えた。
2017年6月中過
SHLD、STA命令とLHLD、LDA命令ができた。それぞれの命令は関連がありよく似ているので回路に共通部分がある。共用部分があるので、そろえて作ったほうが楽だったのだ。
さて、動作確認だ。STEPで動作させるとうまく動作した。
そこで連続動作でテストするためのプログラムを設定した(組んだ)。
LXI H、0AAC5H
SHLD 0F000H
LDA 0F000H
STA 0F001H
LHLD 0F000H
HALT
この結果
Aレジスタ=0C5H
HLレジスタ=0C5C5H
となるはずである。
STEP動作ではうまくいったので、クロック1MHzで実行させてみた。結果は上々、ラクチンラクチン。
では2MHzではどうだろう。
・・・・・えっ! う、うまく動かない。HLレジスタが0AAC5Hのままだ。おや〜。
クロック1MHzのCPUってことぉ〜。いやいやそんなはずは・・・・。
悩んでもしようがない。ロジックアナライザの出番だ!。
あれやらこれやら調べった結果、アドレスのA14の変化が変なことに気付いた。
ロジックアナライザなので、波形は矩形であるが、波形の変化タイミングから元波形がなまっているのではないかと疑った。こればっかり使っていると波形のタイミングから元波形がおかしいのではと何となく分かるようになるものである。
早速A14のラインを調べていくと・・・ビンゴ!。半田不良を見つけた。
手直しすると2MHzでも動作した。
半田不良なのに1MHzでは何故動作するのか?(推測だが)半田不良部は高抵抗で繋がっていて、信号はある程度伝わるのでは。CMOS−ICは入力インピーダンスが高いので、信号を受け取れるのだろう。TTLは電流で動作するのでそうはいかないが。クロックが早くなると高抵抗と浮遊容量でフィルタのようになった部分で信号が伝わりにくくなるのであろう。
さて2MHzが動作したので、試しに4MHzにして見た。・・・・やっぱり・・・・動作しない。そんなもんかなぁ、まあ期待はしていなかったが。ロジックアナライザが繋がっているので、波形を採って見た。
おやっ!アドレスラッチがうまくいってない部分がある。その部分以外はちゃんとラッチできている。・・・・・・あっ・・・・・急に思い出した。半年前に回路設計時に頭をよぎったことが・・・。
おかしくなっているのはSTA命令の後だ、STA命令はSHLD命令を半分つかう。Lレジスタをメモリーに書くかわりにAレジスタを書いて、マシンサイクルをリセットする。リセットしなければそのままHレジスタを書いてしまう。この実行ICのアドレスラッチ信号が生きている(Hの状態、トライステートがアクティブになっている)。これとSTA命令の次の命令をフェッチするためのPCをラッチする信号回路がケンカしている。じゃあ何故2MHzでは動作するのか??これはよくわからん。
命令をフェッチしてしまえば、STA命令実行信号が切り替わるのであるが、フェッチできなければ切り替わらない。実際には強制的にフェッチ動作するので、どこだか分からない(アドレスラッチに失敗しているので)アドレスのデータをフェッチしているので、命令は切り替わるが。
さて改造だ、フェッチサイクルの間(M1ステート)、命令デコーダをディスエーブルにしてみた。ふむふむ、これでどうーーーーだ!。
ありゃっ!動作しない。やっぱり4MHzはだめかねぇ・・・。
もののついでだ、ロジックアナライザで確認すると少し様子が変わった。信号のケンカは無くなったようだが、やっぱりアドレスラッチミスがある。これはなんじゃ。アドレスデータとラッチ信号が同時にでているぞ。どうやらうまく取り込めていないようだ。どうしてPCの出力が遅いのだろう。他の部分は問題無いのだが。
回路図をよーーーーく眺めると。あっ・・(こればっか)、もう一つ思い出した。昨日の晩飯に何食ったか忘れるので仕方ないか・・・、いや、思い出したのだから無問題かぁ・・・。
命令実行完了でマシンステートをリセットするが、リセットした途端にフェッチサイクルのT1ステートになる。だが、時間遅れがあるのでT1ステートの先頭ではない。この遅れが回路図では読めなかったのだ。実際に動作させないと分からん、とその時思ったのを、思い出したのだ。
元クロック16MHzとしていて、2クロックほど遅れている。なので125ns遅れていることになる。アドレスラッチは3クロック目の立ち上がりを使っているので、やはり125nsで出る。これではだめなので、4クロック目の立ち上がりへ変更した。
そこで4MHZで動作させてみると、なんとうまく動作したのである。4MHzで動作してくれれば御の字だ。いやーー嬉しいなぁ。でも、命令実行部を追加していってICが増え、配線が増え、浮遊容量が増えると、動作しなくなるかもしれない。ぬか喜びにならなければ良いが。
クロック4MHzで動作した時の写真(※後日追記:Tnクロックを4MHzで作っているので4MHzと書いてしまったが、Tnの周波数は半分の2MHzとなる。どうやらこれがCPUクロックのようである(汗)。なのでi8080の2MHzと同等であった。)
2017年6月末
STAX、LDAX命令を追加し動作確認OK。これは楽勝だった。続いてMOV命令、MOV r、rである。追加完成して、同じく楽勝と思いきや、Aレジ以外はうまく動作する。うまく動作しないのはAレジへ入れる場合だ。MOV A,r がうまく動作しない。うーーん、またやってしまった。8ビットバスに繋がったAレジスタとB,Cなどのペアレジスタの16ビットバスのデータルートの切り替えでミスっていた。レジスタ指定のrが偶数の場合、B、D、Hレジスタとなり、奇数の場合はC、E、Lレジスタとなる。なのでMOV命令のSourceとDestinayionが偶数どうし、奇数どうしはそれぞれの8ビットバス内だが、違う組み合わせでは、偶数←奇数、奇数←偶数の場合はそれぞれの8ビットバスデータをもう片方へ送るようにゲートを切り替えるようにしている。だが、DestinationのAレジスタは奇数だが、16ビットバス側ではなく、最初に書いたように8ビットバス側にあるのだ。なのでそちら側へデータ送らなければならない。そこが抜けていた。うーーーん。IC1個追加だ。幸い回路見直しで1個不要になった部分があるので、そこに実行部のまだ実装していないICをずらしてスペースを作り1個追加した。
これでMOV r,r命令が完成した。(やれやれ)
MOVのテスト命令
LXI B、0AA55H
MOV A、C
LXI B、0FFFFH
MOV B、A
MOV C、B
MOV D、C
MOV E、D
MOV H、E
MOV L、H
HLT
実行結果の写真
命令を1個づつ追加するのは面倒だと思ってもみたが、こういう事が有るのでやはり命令は1個づつ追加する事にしよう。(やっぱり)。
2017年7月初旬
追加できた命令はINXとCMA、DAAである。
テスト
まずは
LXI B,00FFH
LXI D,00FFH
LXI H,00FFH
LXI SP,00FFH
INX B
INX D
INX H
HLT
とした。INX SPも入れたかったが1バイト足らない。INX HをINX SPに変えて2回テストする。
INX SPに変えてテストした写真。
次にCMAとDAAのテスト。
LXI B,0055H
MOV A,C
CMA
HLT
でAレジスタがAAHになることを確認。
これにDAAを追加すると
ACフラグとCフラグONしていたので、10HとなりCフラグがONしている。
取り敢えず動作しているようである。
でもこのペースだとお盆休みまえには完成しそうにない。
11月ころ完成かなぁ・・・。これだと回路図を書きはじめて1年かかったことになる。あわてて作る必要も無いのでのんびり作るか・・・。
あ、そうだった。DCXもできているのだった。INXとDCXはほとんど同じで、+1するか−1するかの違いなのでほぼ共通回路でできるのだ。写真を撮り忘れていたので、書き忘れていた。
改めて写真を撮り直した。
レジスタに同じデータを入れるならLXIを並べるよりMOVを使った方が命令バイト数が少なくてすむ。
と言うことで実行した命令は
LXI B,0100H
MOV E,C
MOV D,B
MOV L,C
MOV H,B
LXI SP,0100H
DCX B
DCX D
DCX H
DCX SP
HLT
これを実行すると全てのレジスタの値は00FFHとなる。
2017年7月中
MOV r、MとMOV M,rができた。
早速テストだ。
LXI B,0F005H
MOV E,C
MOV D,B
MOV L,C
MOV H,B
MOV M,C
MOV B,M
MOV D,M
MOV A,M
MOV H,M
HLT
とした。これで全部のレジスタが05Hに書き換わった。しめしめ、できたぞ〜。
せっかくなのでC,E,Lレジスタに書くMOVをHLTを除いて追加した。
どーーだと実行させたが・・・・。ありゃ〜。C,E,Lレジスタが05Hにならない。???。
何故?。C、E,L側へデータが行かない?
上に書いたB,D,Aの所をC,E,Lにするとうまく動作した。しばらく悩んだが・・・・。!ひらめいた!!
もう一度冷静に命令を見ると。
LXI B,0F005H
MOV E,C
MOV D,B
MOV L,C
MOV H,B
MOV M,C
MOV B,M
MOV D,M
MOV A,M
MOV H,M
MOV C,M
MOV E,M
MOV L,M
HLT
もうお分かりかな。Lに同じデータ入れてどうすんねん・・・と言う突っ込みは無し。問題はMOV H,Mの位置である。この命令を実行すると、H=05Hとなる(当たり前)。
つまり、この後のMのアドレスは0505HとなってRAMの無い(と言うか何も無い)アドレスを読み出したのであった。この命令を一番最後に持ってきて、めでたしめでたしとなったのである。
その後MOV M,Aなど各レジスタからMへ書く命令をテストした。
LXI B,0F005H
MOV E,C
MOV D,B
MOV L,C
MOV H,B
MOV A,C
MOV M,A
MOV D,M
MOV B,M
MOV D,M
MOV H,M
HLT
を実行したときの写真である。
2017年7月中過ぎ
INR、DCR命令が出来た。早速テストしてみる。
まずはINRから。
LXI B,1010H
MOV D,C
MOV E,C
MOV H,C
MOV L,C
MOV A,C
INR B
INR C
INR D
INR E
INR H
INR L
INR A
HLT
テストした写真。レジスタが11Hとなっている。よしよし。
では、次はDCRだ。INRをDCRに変えて実行。うまくできた。
次に何気にDCRをLだけにしてみた。・・・・!・・・・おや〜、Aレジスタにも同じ値が入る。???。じゃぁ、Hレジスタだと・・・・。やっぱり同じだ、Aレジスタに同じ値が入る????。
では、と言うことでロジックアナライザだ。えっ!ロジックアナライザを繋ぐとうまく動作する。Aレジスタには格納されない。・・・???・・・。
DCR実行部はINR実行部と同一になっている。つまりINRとDCRをORして命令実行部にENABLEを出す。なのにINRでは問題無い。DCR実行に信号が出ない?いやいや実行はしているのだから問題無いはず。この信号だけロジックアナライザに接続してモニタしようとすると現象が出なくなる。おや〜・・・・。分からん。試しに電圧を測ると4.5Vだ。問題無い。ENABLE時はLレベル(ほぼ0V)になるはず。ちなみに他の命令の端子は4.9Vだ。うん・・・。4.9V。いろいろ測ったが全て4.9Vだ。ではDCRのところは何故に4.5なのか?う〜〜ん。眠い。今日は寝よう。
さて、翌朝目が覚めたとたん閃いた。きっと寝ている間に脳が勝手に考えていたのかも。それは、VCCが浮いているのでは、と言うこと。早速テスターで当たってみると、ビンゴ!。VCCが浮いていた。そこからVCCを接続しているINR,DCR実行部も道連れにVCCが浮いていた。出力の寄生ダイオードまたは入力保護ダイオードを通じて電圧が掛かっていたのだ。でもCMOSなので動作してしまう。
VCCをチェックして問題部を修正した。
では、どうだ。・・・・ありゃりゃ。ダメである。Aレジスタのラッチ信号をロジックアナライザでモニタすると、DCR命令時にAレジスタラッチ信号に細いパルスが出ている。DCRの対象レジスタにかかわらず、いつも出る。何故だぁーー。 そうだ、一晩寝てみよう・・・・goodnight
翌朝・・・なにも閃かなかった。・・・しゃあない、調査だ。DCR回路のAレジスタラッチ信号をはずして(浮かせて)、ロジックアナライザで観測すると、ややっ!立派なラッチ信号が出て来た。つまりラッチ信号がケンカしていたのだ。
ではDCR命令実行時に同時に動作する命令があるはず。回路を追っかけると・・・、あった!。CMA命令が動作してしまう。なぜに・・・、あっ!そうか。昨年の11月に回路最終段階の見直しでINR、DCR命令を変更したのを思い出した。元の回路は+1、−1カウント回路で+1−1していたが、これではフラグが変化しないので、ALUで+1−1するように変更したのだった。
ADD命令とSUB命令を使っても良いが、それではステップ数が多くなるので、なにか方法は無いかと74HC181のデータシートと別にゲットしたロジック表をににらんで、S、M信号とC(キャリー)の組み合わせで、入力Aの出力がA+1の場合とA−1の場合があることが分かった。+1する場合は現状の回路(通常S,Mが全てHレベル)にC=1(Hレベル)にすればA+1が出力される。なのでINCの場合はCをHにするOR回路を追加した。−1する場合はS,Mを全てLレベルにすれば良い。現状の回路ではCMAとADDの信号を同時に入れると良いので、そのように回路を作成したのである。
ではADDもまずいのかと言うとこれは大丈夫である。演算命令(ADD,SUBなど)実行にADDするかSUBするかの選択信号としていて、トライステート出力となっていてケンカしない。CMAは単独の命令実行指令なので、これにDCRを入れるとこの信号自体もケンカしているのである。
CMA命令作成時はDCR命令部は未実装だったので、動作確認で気付かなかったが、もしDCR命令を先に作っていたらCMA命令で悩んでいたかもしれない。
ALUに入れるCMAの信号を余ったOR回路でCMA、DCRをORして接続した。
これでようやくDCR命令が完璧に動作した。
ついでにCMA命令も追加してテストした写真。
2017年7月末
RRC、RAR、RLC、RAL、INR M、DCR M、CMC、MVI Mが完成した。
早速テストした。今度はあっけなく動作した。スルッと動作しても面白くないが・・・。とりあえず動作したのでOKとしよう。(写真は無し。あってもランプが点灯しているだけでつまらない?・・・)
2017年8月初日
MVI r ができた。早速テストした。
MVI B,1
MVI C,2
MVI D,3
MVI E,4
MVI H,5
MVI L,6
MVI A,7
HLT
うまく動作した。ランプが点灯しているだけだけど、寂しいので写真をアップ。
2017年8月中
お盆の帰省で中断していたが、ようやく再開して命令を作った。
SPHL、PCHLがまずできた。
取り敢えず動作したので、PCHLを使って0番地へ戻るようにしてループさせて、長時間ランニングしてみた。特に問題なく動作している。
次に作ったのは
POP、RETとRXX(条件RET)である。なぜに先にPOPだけかと言うと、回路図の順番がそうなってしまっただけの事だ、深い意味は無い。(当然?)
メモリーにデータを書いておいてPOPで取り出すテストを実行、問題なく動作した。
RETも戻り番地をメモリーに書いてRETで取り出すとそこへジャンプする。これも戻りを0番地にして、ループさせてみた。問題なし。
さて条件RETだが、条件が成立してRETURNする場合は問題無いが、条件が成立しなかったときに次のステップに進むはずのところが、次の次へ飛んでしまう。
ロジックアナライザで確認すると、条件不成立時の命令クリアが思ったより遅く、次の命令のアドレスラッチに間に合ってない。以前書いたようにアドレスラッチは4クロック目だが、これが最後のクロックなので、これ以上遅らせられない。もともとのタイミング設計がまずいのであるが、ここまで作ってしまったら致し方ない。クロックカウントもクリアするように変更するしかない。こうすると、命令実行時間の見積もりが難しくなるが、動作しないよりはまし、と言うことで改造した。なので命令実行時間はマシンサイクルの時間+アルファ(命令リセットの遅れ)となってしまった。
もし製作途中でうまい方法を考え付いたら改造するかもしれない。
2017年8月中
引き続き、PUSH命令を実装した。
では、テストだ。
LXI B,0AA55H
PUSH B
POP D
PUSH D
POP H
PUSH H
POP PSW
HLT
さーーあ、どうだ。・・・・おやっ?、うまく行かないぞ。・・・・
あっ!、まずいじゃん!。
LXI SP,0F000H
LXI B,0AA55H
PUSH B
POP D
PUSH D
POP H
PUSH H
POP PSW
HLT
そう、スタックポインタを設定しなければ。
さあ、どうだ。・・・・やっぱりうまく行かない。
やれやれ、ロジックアナライザの出番だ。
どれどれ、おや〜。スタックポインタを−1する、最初の信号が出てこない。命令実行タイミングのマシンクロック1クロック目で−1する信号を作っているが、命令実行部のトライステート出力のENABLEも同タイミングで入る。以前M1で命令デコーダをブロックするように改造したので、M1解除で命令出力信号が出て、それをHC04で反転させてENABLE信号としているので、実際に−1信号が出力に現れるのが遅れて出てこない。ENABLEでトライステートが有効なったときは2クロック目になっているのだ。これではどうあがいても−1信号が出てこない。そこで仕方なく、−1信号は2クロック目を使うことにした。ただし、こうするとアドレスラッチを3クロック目にしているので、スタックを−1した結果がアドレスラッチに間に合わない。
案ずるより産むがやすしで実際に動作させると、うまく動作した。いいのかなあ〜。スタックのカウント完了からアドレスラッチまでの時間をロジックアナライザで見てみると、10〜20nsになっている。
ちょっときわどいので、アドレスラッチ信号を1段バッファを通して遅らせてみた。これで先の時間は20〜30nsとなった。
取り敢えずこれでしばらく様子を見よう。
2017年8月末
次にできたのは、CALL、CXX(条件コール)とOUT命令だ。
早速CALLをテストしたがうまく行かない。やっぱりスタックのところだろうと当たりを付けてロジックアナライザで見てみると、やっぱりそうであった。この回路ではアドレスラッチがスタックの−1カウント完了よりわずかに早い。PUSHみたいにゲートを入れてもギリギリだからこの手も使えない。しばらく悩んだが、ラッチ信号を反転させよう。つまりインバータ(HC04)で反転させるとラッチの立ち上がりエッジが62.5ns遅くなる。ゲートの信号が命令のENABLEで出たとたん1回ラッチされてしまうが、その直後正しいデータ(アドレス)がラッチされる。
試しにやってみるとうまく動作した。みっともない方法、邪道かもしれないが自分で使うマイコンなので良しとしよう。出来た暁には回路図をアップしようと思っていたが、突っ込みどころ満載の回路になってしまったので、止めることにしよう(ヤレヤレ)。
ところでOUT命令はIN、OUTのテスト回路を搭載するのを忘れていたのでテストできない。IOREAD、WRITE信号が出ているのを確認しただけだ。
ケースに収めた時のパネルの回路でIOを使っているのでその時のお楽しみだ。
2017年8月末
次にIN、XTHLとRST作成。これで最後だ。
さて、XTHLの確認。実行と同時にどこかへすっ飛んだ。おや〜、ロジックアナライザだ。でもよく分からん。再度回路を確認。あっ!、しまった。XTHLはスタックからデータを取り出してWZレジスタへ退避して、HLレジスタをスタックに書いて、WZレジスタをHLへ書く動作だが、WZレジスタへのアクセスはCALLでも使っている。CALLの場合は命令に続く飛び先アドレスをWZレジスタへ入れておき、PC(プログラムカウンタ)をスタックへ入れて、PCへWZレジスタのデータを書くと飛び先へ実行が移る。このWZレジスタの部分をコピーしてそのままだったのだ。つまりスタックへ入れた適当なデータをPCへセットしてしまっていた。(やれやれ)。早速修正。WZレジスタをHLレジスタへ書くように変更。無事動作した。
次にRST命令だ。固定(8とおり)のサブルーチンコールと同じである。まずスタックにPCを退避、RST命令による飛び先をPCへセットする。まずスタックに退避するので、PUSH命令と同じタイミングを流用して作成。問題なく動作した。
CALLと同じにしなければならないかとも思ったが、PUSHと同じタイミングで大丈夫だった。
2017年9月初
さて、取り敢えず命令が完成した。およそ210日掛かったので、やっぱり20本/日のペースだったことになる。
では、連続命令テストをやってみよう。DIPSWのROMではステップが不足なので本物のROMに登場してもらおう。
ROMに書くテストプログラムはあらかじめダウンロードしたaltair8800_emulaterを使ってCP/Mを動作させ、CP/M上で動作する8080命令テストプログラムを、このDEBUGボード用に修正してコンパイルした。出来上がったリストとHEXファイルをWINへ転送して、HEXファイルをターミナルソフトでPROMライターへ転送してROMを焼いた。
PROMライターは押入れから発掘してきた。同時にPROMも発掘。PROMはいろいろあったがMB8532を使用、4kバイトのPROMだ。そんなに容量はいらないがこれが最小容量のPROMだった。
発掘したPROMライター
もう何年も電源入れてないので、恐る恐る電源入れたら、セルフチェックしてOKと出た。一安心。
使い方を忘れてしまったので、ADVANTESTからマニュアルをダウンロード(便利になった)。
RS232Cのコネクタが25PINコネクタだ。今時見ないコネクタである。たしかどこかに25ピン−9ピン変換コネクタがあったはずだが・・・。もう何年も使ってないし・・・、押入れを探したが発掘できなかった。仕様がないので、とりあえず9ピンのメスコネクタをつかって変換を作った。と言っても25ピンが無いのでこちら側はリードをコネクタのソケットに直接差し込んでみた。
マニュアルを見ながらHEXファイルを転送するとうまく転送できた。INTELのHEXファイルにも対応しているので簡単であった。当時のPROMライターは色んなHEXファイルに対応している。
PROMに書き込んでDEBUGボードに装着した。
さあ、実行だ。
直ぐにずっこけた。ありゃ!。エラーの場合はHLレジスタにエラー発生場所のアドレスが入るようにしているので、リストで確認すると。ん、キャリーフラグがONしていない確認でエラーになっている。確かにキャリーがONしている。これはLOGIC演算(AND,OR,XOR)でキャリーがOFFしていることのテストでエラーになっている。
ありゃ〜。LOGIC演算でキャリーOFF??。8080のマニュアルを見ると、確かにキャリーはリセットされると書いてある。回路の作り忘れ?。う〜ん。記憶のかなたにうっすらと・・・。
そうだ、ALUがよろしくやってくれると思いその後全く気にしていなかった。ALUのA=Bのテストでやっておけば良かったのだが、その時はすっかり記憶のかなたであった。
余ったゲートでなんとか出来そうだ。早速追加して動作確認(DIPSWのプログラム)OKである。
後日追記
よく考えたら、ACは(ハーフキャリーとも言っている)はどうなのだろう。ALUは4ビットで2段接続している。下4ビットのキャリーを上4ビットにいれて、これをACとしている。つまり論理演算でCがONするならACもONするはずである。試すとやはりACがONしている。そこで疑問。DAA命令のテストでACをクリアするためにOR命令を実行している。OR Aを実行すると・・・。ACはONしない。つまりCもONしない。うん。ALUまかせでもよかった??。いろいろ試すと、論理演算のsourceとDestinationの値が同じ場合はAC,CがONしないことが分かった。8080のマニュアルのはCはゼロをセットすると書いてあるが、ACは結果が反映されると書いてある。ゼロをセットするとは書いてないのでなんらかの状態に変化するのであろう。実際にどうなるかは8080が無いので分からない。
ちなみにDAAのテスト前でACをクリアする命令としてOR Aとなっているので、Aレジスタに何が設定されていても同じデータどうしなのでACはクリア(OFF)される。もしかしたら8080も同じ動作かもしれない。OR AとしなければACがクリアされないのかも。
追記ここまで
ではPROMのプログラムスタート。OKだ!。よし!やったーー。出来たぞ!(実はぬか喜び)
次に連続動作スタート・・・・。おや、ずっこけた。連続動作のパスカウントを調べると3が入っていた。3回はうまく動作して4回目でずっこけたことになる。
少なくとも、1回は動作するので、命令の実行シーケンスには問題なく、タイミングに問題がありそうである。
タイミングの問題だと難しそうだ。
さっそくLOGICアナライザを接続。HLT命令で停止するので、そこをトリガにする。早速エラーで停止した。調べるとCPI命令で比較したときにデータは等しいのでZフラグがONするはずが、ONしていない。Zフラグの信号がふらついている。どこかにまだ半田不良があるようだ。ALUにLOGICアナライザを接続して再実行、どうやらD1ラインが不良のようだ。半田をやり直してOKとなった。
さあ、ではこれでOKか。テストプログラム実行!。ありゃずっこけた。こんどはどこだぁ〜。またもLOGICアナライザを接続、調べるとINX命令の後でエラーとなる。何故に??。INX命令の動作を調べると、INX B、INX D,INX Hと実行するのだが、どの命令でもBCレジスタが選択される。ええっ〜。INX D、INX HでBCも同時に選択されるので、データがケンカしている。やれやれ。
選択信号が他の選択信号と混触してるのかなぁ。半田不良かなぁ。とりあえず半田ごてを当てて再半田してみたが、直らない。混触かもと思い、BC選択信号を出す所の配線をはずしてみた。信号は無くなって安定している。混触は無さそうだが・・・はて。再度配線を接続した。おや、直ってしまった。半田不良だったのかなぁ。ここも再半田してみたところなんだが、不十分だった??。
直ってしまって現象が出ないと調べようがない。連続動作で評価を続けるしかないかなぁ。
さて、最終的に出来た表の部品搭載状況だ。
ちなみに裏側。配線がカオス状態。
ROMのテストプログラムを連続動作中。写真ではよく分からんが。
2017年9月初旬
あぁ、そうだ、RAMとROMのタイミングについて書いてなかったので少し。
RAMはHM6264LP−15で150ns。当時のRAMとしては遅い方だ。でも4MHzクロックだと問題無い。
P−ROMはMB8532−35である。350nsなので、早い方だが、4MHzクロックだとギリギリなんとか読める。
手持ちのP−ROMを見るとMB8532−35とMB8532−45が混在していた。当時はあまり気にしてなかったのかなぁ。もうすっかり記憶のカナタである。
どうやら連続運転は大丈夫そうである。これから周辺機器の設計製作である。
押入れから古い物を発掘した。
確かPC−6001の拡張BOXからBUS信号を引っ張り出すIFボードと拡張MEMORYボードだったと思う。
さらに、その拡張に装着するFDDインタフェースボードである。
確か、これで8インチFDDをドライブしてLOAD、SAVEしていたような。左の細長い追加のボードは後で追加したクロック成形回路だった(はず)。
真ん中のLSIがINS1771N−1で、FDDをコントロールしてデータを読み書きするのだが、トラックの中央より(トラック番号の大きい方)のデータリードミスが多かった。
それを改善するには読み取ったクロック波形を成形して1771に入れると改善できると何かの雑誌に書いてあったので、その回路を追加したのだった。
でも、それほど改善できなかったような記憶がある。
今でも動くのかなあ。FDDが無いので確認のしようが無い。
あっ!これらを使うつもりはありません。今では1チップで32kBのメモリが入手できますから。それからFPGAも。
2017年9月
ケースに入れようとして検討したら、横幅400mmの大きなケースになってしまった。なにせCPUが1枚ボードだから仕方ないかな。
(ツ)さんに発注していたケースが届いた。これからケースの加工だ。
2017年9月中
パネルの加工をやっている。文字をいれようとレタリングを取り出したら数字がなかったので、数字とついでに文字も手配。とどくまでお休み・・・?
2017年9月中
レタリングが届いたので、文字を入れてクリアラッカーでコーティングした。ただ今乾燥中。
えっ!D1が少しズレている?。ほかにも?・・・・ええ、これは手作り感を出すためにわざとずらし・・・・・・。はい、不器用なのでズレてしまいました。DとPは8個しか無かったので、やり直せなかったのですぅ!
2017年9月末
LEDを取り付けようしたがバリが出ている(なんだかなぁ)。安いからしょうがないのかもしれないが大陸製というのもあるかも。しかもLEDは後ろから嵌めてあるだけだ。なのでパネルに取り付けてもLEDを前から押すと後ろへ抜けてしまうと思われる。
バリが出ているのがお分かりかな。しかもスプリングワッシャーのような物も変、捻りが逆である。ワッシャーとして役に立たない(やれやれ)。適当に形だけ真似るからこうなるのであろう。
LEDは後ろへ抜ける。普通の砲弾型LEDがはめ込んであるだけ。
バリを取るとき気付いたが、バリはカッターで切り取れた。材質は亜鉛(合金)のようである。日本製の真ちゅう削り出しにクロムメッキでは無い。
亜鉛合金のようなので、ネジを締めすぎると首の所で破断しそうだ。ネジ締めは気を付けないと・・・。
ようやく組みあがった。
さて。配線しなければ。
2017年9月末
LEDの配線をコネクタ接続としたいのだが。LEDのリードとコネクタをユニバーサル基板で接続しようとすると半田付けが裏表でやりにくい。コネクタを先に半田付けしてLEDに基板を付けて半田付けしても配線が・・・。そうだ、LEDは後ろに抜けるので、まずLEDを半田つけして、LEDごと外してコネクタを半田付けして配線することにしよう。
で、やってみた。
LEDを基板に半田付けして、後ろに抜いたところ。この後コネクタを付けて配線した。なるほど後ろに抜けるのはこのためかぁ・・・・(ホンマかいな)。
LEDとSWの配線をやってパネルを組んでみた。
別の角度から。
見れば動作しそうな感じだが、まだこれでは動作しない。なにせ1枚でCPUチップと同等なので、言わばCPUチップだけ搭載したようなものだ。SWの読み込み、LEDの点灯、メモリーなどが必要だ。
2017年10月初旬
パネルインタフェースとメモリー回路を鋭意製作中だ。
2017年10月中過ぎ
ようやくSWインタフェースとメモリーの部分ができた。実装してSWからパチパチとプログラムを書き込んで実行させてみた。
メモリはまだPROMが出来ていない(プログラムが出来てない)のでRAMだけ。64kBのエリア全てRAMの状態だ。
あと、TEK2782の修理で余ったSPARTAN−6のFPGAを載せてSDカードを外部記憶替わりとする予定。さらにSDRAMをビデオRAMとしてカラー(8色)表示もするつもり。どこまで出来るやら・・・。
RAM2個で64kB。ちょっとブレたかな。
取り敢えずRUN。プログラムは入って無いので暴走状態。この後SWから少しプログラムをインプットしてRUNさせてみた。昔はこうやって動かしていたのだが。
2017年10月下旬
簡単なモニタプログラムを作ってROMに焼いた。機能はメモリの読み書き、IOの読み書き、HEXファイルのロード、ブレイクポイント1つ、レジスタ表示、変更である。簡単なデバッグはできる。昔々を思い出しながら製作した。(昔のデバッグはこんなんだったんだよ〜)
早速、命令テストプログラムをRAMで動作するように書き換え、正常パスカウント値を黄色のLEDに表示するようにした。HEXファイルの作成はaltair8800_emulaterでCP/Mを動かし、コンパイルしてHEXファイルを作る。それをターミナルソフトで流し込む。
早速RUNさせると、途端にエラー停止。んっ!何故に止まる。エラーの箇所を調べるとCMA命令がエラーとなっている。ああぁDCR命令でケンカしていたところだ。でも修正確認したよなぁ・・・。って言うかROMのテストプログラムで動いていたじゃん・・・。半田不良??
バラしてロジックアナライザを接続。やっぱり半田不良っぽい。ALU回りを入念に再半田した。
さあどうだ。再度組み立てて、命令テストを開始。おお、動いた動いた。15分ほどしたら止まった。えっ!、う〜ん。今度のエラーはCMAではない、CPI命令だ。ZフラグがONしているはずがONしていない。いや〜まだ半田不良が・・・。
また分解。フラグレジスタ回りを再半田。もう他に無いか、DEBUGボードでテスト。動作させながらICを指でコツコツはじくと特定の場所で動作停止する。その辺に半田不良が有りそうだ。そのIC回りを再半田。指でコツコツはじいても動作停止しないようになった。ヤレヤレ。
そういえば半田のやり方が前半と後半で違っている。DEBUGボードの製作より前が前半で、後が後半である。後半で製作したのは命令実行部だが、こちらは半田不良がでない。
前半の半田はICピンに1回巻きで半田鏝の熱で被覆を溶かすやり方と、線の先端を半田メッキしてICのピンへ半田付けする方法だった。しかも半田鏝の温度は後半より少し低い。当然半田付け後にテスタで100%導通チェックはしたのだが、付きが弱いのか時間とともに取れるようだ。鏝の温度が低め(被覆を溶かすには)だったので被覆が十分に溶けないのと、半田メッキしてICピンへ付ける方法は良さそうだが、ピンの隙間に先端が入り、入り過ぎて半田部分から向こう側へ突き出てしまっていた。
DEBUGボード製作時にこれに気付いたので、その後はICピンに2回巻き、先端を半田メッキしたあとは付き出ないように1回巻きで半田付けした。しかも半田鏝温度を高く設定した。しかも2回巻くと力強く巻けるので、巻いただけでピンの角で被覆に切れ込みがはいり導通する。そこへ半田鏝を当てると熱が線に伝わりやすく被覆が溶けるのが早い。
前半では導通チェックで半田不良が見つかっていたが、後半では100%不良はでなくなったので、後半の途中から導通チェックは省略した。
結果やはり前半部分での半田不良がでる。後半からは出ていない。
ROMとFPGAを装着してみた。FPGAの中身はこれから。ケーブルが繋がっているのはUSB−パラレル変換器。最初はUSB−RS232C−パラレルにしようと思っていたが、RS232Cにする意味が無いことに気付き、急遽USB−パラレル変換を付けた。モニタソフトはこれでPCと通信する。
2017年10月エンド
書き込みが遅くなったが、この時期やっぱり不具合が見つかった。それは条件CALL命令だ。条件が不成立でCALLされなかった時の挙動がおかしい。スタックポインターが1つ減ってしまう。命令テストプログラムでは発見できなかったが、アプリで発覚した。サブルーチン内で条件CALLして、不成立で戻ろうとするとスタックが狂っているので、暴走したのだ。
原因は命令リセット回路である。以前、命令完了でリセットするやり方で、命令完了の次のクロックの頭でリセットしていることを書いたが、それが災いしていた。命令不成立で、次のクロックの頭でリセットを掛けるが、不成立でない場合はCALL先へ飛ぶ動作となる。そのため、現在のプログラムカウンタをスタックへ退避するため、スタックポインターを一つ減らす動作に入る。これが同時に起こるのでスタックポインターが一つ減ってしまう。
そこで、命令リセットのところで、良い考えがあれば変えるかもと書いたが、実は良い考えが出来てはいたのだが、面倒なので実施していなかった。それは、命令完了後のクロックでリセットするのでは無く、命令最後のクロックのその最後でリセットする方法である。実施するには、全ての命令のリセットクロック信号の配線がやり直しとなってしまう。取り敢えず動作しているのでそのままにしていた。
でも、ここだけはそうはいかない、命令条件不成立で実行をブロックする手もあるが、考えたリセット方法の検証の意味もあり、リセットタイミングをCALL命令のアドレス取得完了のクロック最後でリセットする回路にした。結果うまくリセットできて動作にも問題無い。
他の命令全てこの方式に変えるとすっきりするのだが、手間が・・・・。
2017年11月初旬
気付くと、回路設計を開始して1年になる。月日の経過は早いものだ。道理で歳をとるのが早いはずだ。取り敢えずBOXに入って動作を始めたので、1年で完成だ!!
これからCP/Mの移植に入る。FDDなんて無いから、いや無くはないがSDCARDなるものがあるので、これをDISK代わりにしよう。
早速、FPGAでSDCARDを読み書きする回路を作成している。いろいろネットで手順をさぐっているが、難しいなぁ。
2017年11月中旬
SDCARDの初期化ができたので、2GのSDCARDを入れて試してみた。うん、うまく・・・・・いかない! ?。
FPGAの回路はどうも取っ付きにくい。ついついソフトのように書いてしまう。ハードなので同時実行なのだが・・・。
なんとか読み書きできるようになった。ものの本に初期化クロックは400kHzくらいと書いてあったので、そのようにしていたが、ネットで早くてもOKと書いてあるのを見つけた。早速、クロックアップしてみたが、全然大丈夫である。最終的には10MHzクロックとした。
2017年12月中旬
さんざん苦労してSDCARDの読み書きが出来るようになって、CPMのBIOSを作成した。何度かバグ退治していると一月ほど経過してしまった。
まずはSDCARDだが手元に2GBのカードが2枚ある。1つはCMD0→CMD1で初期化できるが、もう一つはそれではだめで、CMD0→CMD8→CMD55→ACMD41としなければならない。
CMD8はどちらも有るので、CMD0→CMD8→CMD55を送ってレスポンスがエラーだったらCMD1を送るようにした。
ACMD41を送らなければならないカードは以前スマホで使っていたのパーティションをWinとスマホ(Android)に分けていたせいなのか、MBRが2重になっていた。
通常だとディレクトリの場所をたどるのに、MBR→BPB→FAT→DIRとなるのだが、パーティションを分けていて、削除してフォーマットし直したにもかかわらず、MBR→MBR→BPB→FAT→DIRと辿らなければならなかった。最初のMBRでWinとAndroidを分けて、そこから通常のWinのMBRになるようだ。フォーマットしなおしてもここは残っていて、Win側のMBRで全体の容量が使えるようになっている。
BIOSのディスクパラメータをAltair8800emulaterで書いたディスクイメージが使えるようにした。SDCARDの1セクタは512バイトだがCP/Mの1セクタは128バイトなのでBIOSでバッファしてREAD、WRITEするようにした。READは4セクタ毎にSDCARDから読めばいいので簡単だが、書き込みは悩んだが、書きたいセクタのSDCARDのセクタを計算して、読み出して、その中の128バイトをメモリに書いてそのまま512バイトを書き戻すようにした。同じSDCARDのセクタであれば2度読みはしないようにはしたが、128バイトの書き込みの都度、512バイト書いてしまう。出来れば書き込み回数は減らしたいところではあるが、取り敢えず良しとした。キャシュ的にして、512バイトデータ変更部がたまってから、またはSDCARDの異なるセクタの書き込み要求時に書き戻す、書き込みが終了したら書き戻すのが正解かもしれないが、自分で使うのみなので、安易な方法とした。
Altair8800emulaterで作成したディスクイメージがそのまま使えるようにしたので、そこに入っていたアセンブラやBASICがそのまま移植できた。
BOOTしてディレクトリを表示したところ
LADDERと言うゲームがあったので起動してみた。
ところが、このゲームを終了するとHALTしてしまう。最初はBIOSをバグったかと思って調べると、CCPの部分とBDOSの部分にパターン(DATA)を持っていて、それが不一致になるとHALTする。CPM22のソースにもコメントでパターンが異なるとHALTする、WHY?と書かれているので、なぜこのような仕組みになっているか逆アセンブルしてコメントを付けた当人にも分かっていないようだ。
私の脳味噌ならぬただの味噌で考えてみたが、CCPエリアのパターンとBDOSエリアのパターンを比較しており、どこにも書き込むプログラムは存在しない。CCPエリアはWarm boot で再読み込みするが、BDOSは読み込まない。なのでBDOSエリアは破壊されると困るのは確かだが・・・。BDOSエリアが破壊されたと判定してHALTにして、アプリ開発者に知らしめるのかなあ・・・。HALTせずにCold bootでも良さそうだが・・・?
アプリが59kBCP/M用では無いと言えばそれまでだが・・・。
DISKドライブ数を8にしたのでバッファエリアにそれなりの容量が必要なので、59kになってしまった。BIOSをできるだけROMに入れると少しは容量が増えて60kCP/Mには出来そうだが、今後の課題としておこう。
2018年1月中
気づけば2018年も半月が過ぎた。取り敢えずCP/Mが起動できたが、まだ細かい部分がうまくいかないのを、動作確認しながら修正した。例えば、WMでプログラムを編集して終了したときに、必ずAドライブに戻ってしまう。Aドライブで編集していると気づかなかったが、BやCドライブで編集してもAに戻る。ウオームブート後にCP/MへジャンプするときCレジスタにカレントドライブ番号を入れておかなければいけないのが、入ってなかったのだ。などなど・・・。
ところがこれが災いしてか、存在しないドライブに切り替えたときエラーとなるが、コントロール+Cでウオームブートして再び、エラーとなる。つまりカレントドライブの存在しないドライブへアクセスして、再度エラーとなる。これを永遠と繰り返す・・・。なんだかなぁ・・・。CP/Mのソースを見てもコントロール+Cで単にウオームブートへジャンプしているだけ。う〜ん、どうすれば・・・・。暫し考えよう・・・。
2018年2月初
やれやれ2月になってしまった。
FPGAボードのDRAMにMDK8080からデータを書き込んで、それをVGA信号で出力する部分を作成していた。MDK8080からデータを書くときにミスることがあり、いろいろ調べると、MDK8080の5V系からFPGAの3.3V系の変換機器が誤動作しているようだ。秋月で買った変換機で双方向自動切換えなのだが、データバスは双方なのでこれで良いがアドレスやIO、MEMORYのREAD/WRITE信号は一方向なので自動切換えは不要である。よく調べるとデータも不安定だ。時々化ける。なのでデータバスは74HC245を付けて、変換機が方向を間違ってもMDK8080側へ影響が及ばないようにした。でもアドレスやREAD信号なども影響があるのでバッファを入れた。自動切換えは良さそうで、あまりよくなかった。意図した方向になってくれない。
さて、方向を固定したが(データバスは違うが)まだ動作がおかしい。さらに調べるとIOWRITE信号にノイズが載っているようだ。う〜ん、配線の引き回しがまずいのかなあ。しようがないので、FPGAでチャタリング防止回路のような回路で読むことにしてずいぶんと改善された。でもまだときどきおかしい時がある。ほとんど問題なく動作するのだが、忘れたころWRITE信号を見落とすことがある。ほとんどSDCARDの読み出しコマンドの書き込み(WRITE)を見逃すので、データREADで待ちぼうけになって、だんまりになる。待ちぼうけにならないように監視タイマーを入れると良いのだが、そこまでやっていない。
ふつうに遊ぶにはぜんぜん問題ないからだ。
ZORKを遊んでみた。
2018年3月
BDS_Cを入手した。昔昔買った使い方の本を発掘してきた。これは文法書ではなく、タイトルどおり使い方だ。8080のCP/Mで動作させる説明となっている。早速開いて見たがすっかり忘れている。ミスプリを修正した痕跡があるので、当時、一所懸命読んだのであろう。が、記憶のかなたである。
早速、テストプログラムを作って起動すると・・・、動作はうまく行くが、終了でHALTする。おやおや、LADDERゲームと同じだ。何故だろう???。
DDTを使ってデバッグすることにした。
デバッグ開始してすぐに気づいたが、6番地から2バイトデータを取ってきてスタックにセットしている。6番地は、BDOSコールの5番地の飛び先なので、BDOSのエントリポイントとなっている。そうかぁ、BDOSの先頭をスタックにしているのかぁ。つまりCCPエリアはスタックで壊れる仕掛けになっている。でも、BDOSのエントリはピッタリの番地ではなく6番地ずれている。たとえばD806番地の様に、HALTにするチェックパターンはこの前の6バイトになっている、D800〜D805がチェックパターンになていて、CCPにあるパターンと比較して、違っていたらHALTする。
でもここをスタックとして使うのだから、絶対に壊れる。これではCで作成したプログラムを動作させると必ずHALTすることになる。やれやれだ、CP/Mを改造してHALTせずに0番地へジャンプさせようか、そうするとウオームブートするはず・・・・。じゃない、HALTするのはウオームブートの後なので、そんなことするとウオームブートを繰り返すだけである。
うーーん、しょうがない、BDOSの先頭1セクタをウオームブートで読み込むことにしよう。
そこで、ウオームブートを改造してROMを焼き直した。早速ためすと・・・・。うまく行った!。よし!
これでLADDERの終了もうまく行くようになった。
つづく