復活!CP/M ワンボードマイコンでCP/Mを!
CP/MがTK−80互換のワンボードマイコンの上で復活します
ND80ZVとMYCPU80の上でCP/Mが走ります!
[第509回]
●E−80ミニコンOS(CP/M互換DOS)のRS232C割込み受信プログラム
またしても中2日、間が空いてしまいました。
来週はまた週明けからハードなスケジュールになりそうです。
しかしそんなことばかり言っておりますと、懸案のE−80の232C受信プログラムが片付きませんから、昨日あたりから、まずは記事に仕上げようとして書き始めたのですが。
リストをアップして説明を書き始めましたら、「うう、これは、まずいんじゃないの?」というところがぽつりぽつりと見つかってしまいました。
そこで記事をアップするのはとりあえず一時中止いたしまして、本日は朝からずっとそのあたりのプログラム修正やらデバッグやらをやっておりました。
日が沈むころになりましてから、やっとZB3BASICについてはデバッグが完了いたしました。
でもまだCP/M互換DOSについては、検証ができていません。
そちらのほうも少しずつ進めながら、説明を書いて行くことにいたします。
当初の予定では今回一回でその説明は完了するつもりだったのですが、またまた何回かにわたって書くことになってしまいそうです。
まずは今までの説明の続きから始めることにいたします。
[第506回]では、大分県のH様の指摘によってみつかった、ZBIOSのREADER(RS232C受信)プログラムのバグ訂正を行ないました。
ところでそのリストを見ていただければわかりますが、RS232C受信プログラムとは言うものの、受信らしきところはどこにも見えません。
その実体は、アドレスE423でCALLしているRSRDSB(アドレス0409)です。
といってももう何日も前のことになってしまいましたから、ただ言葉で説明しただけでは、よくわかりませんですね。
下にZBIOSのREADERルーチンのリストを再掲いたします。
; ;PUNCHER OUT(RS232C OUT) ; E404 ED PUNCHJ:DB ED;IN0 A,[04] E405 38 DB 38 E406 04 DB 04 E407 E602 AND 02 E409 CA04E4 JP Z,PUNCHJ E40C ED DB ED;OUT0 [06],C E40D 09 DB 09 E40E 06 DB 06 E40F C9 RET ; ;READER IN ; E410 2274E2 READERJ:LD (HLWK),HL E413 210000 LD HL,$0000 E416 39 ADD HL,SP E417 2276E2 LD (SPWK),HL E41A 2A74E2 LD HL,(HLWK) E41D 3100E9 LD SP,BSP E420 AF XOR A E421 D339 OUT (39),A E423 CD0904 READERJ2:CALL RSRDSB E426 CA23E4 JP Z,READERJ2 E429 79 LD A,C E42A C379E3 JP CONSTJ1 |
アドレス0409はCP/Mではユーザープログラムがロードされる0100〜のユーザーエリア(トランジェントエリア)にありますから、普通はシステムがCALLするアドレスではありません。
ここではメモリバンクを切り換えて、ZB3BASICのシステムルーチンをCALLしているのです。
アドレスE420の
XOR A
OUT (39),A
がメモリバンクを切り換える命令です。
この命令の実行によって、アドレス0000〜7FFFのメモリエリアが切り換えられ、CP/M互換DOSのユーザーエリアが裏に置かれて、代わりにZB3BASICのシステムプログラムエリアがアクセス可能になります。
そしてこちらがZB3BASICのエリア(メモリバンク0)にあるRSRDSBです。
046A F3 RSRDSB:DI 046B E5 PUSH HL 046C D5 PUSH DE 046D ED5B00F9 LD DE,(BFTOP);E=BFTOP,D=BFEND 0471 3A03F9 LD A,(RSERR) 0474 B7 OR A 0475 C29504 JP NZ,RSRDSB3 0478 3A02F9 LD A,(BFCNTR) 047B B7 OR A 047C CA9104 JP Z,RSRDSB2 047F 2100F8 LD HL,SPTOP;=RSBF 0482 6B LD L,E 0483 4E LD C,(HL) 0484 1C INC E 0485 ED5300F9 LD (BFTOP),DE 0489 3D DEC A 048A 3202F9 LD (BFCNTR),A 048D C29104 JP NZ,RSRDSB2 0490 3C INC A;reset ZF 0491 D1 RSRDSB2:POP DE 0492 E1 POP HL 0493 FB EI 0494 C9 RET 0495 D1 RSRDSB3:POP DE 0496 E1 POP HL 0497 37 SCF 0498 C9 RET |
E−80のシステムプログラムによるRS232C受信は割込みによって行なわれます。
しかし上のリストのプログラムは割込みプログラムではありません。
単に受信データバッファ(F800〜F8FF)を読んでいるだけで、RS232C受信らしいところはどこにもありません。
割込みプログラムはこれとは別にあります。
なかなかに複雑な仕組みなのです。
ここではBFCNTR(バッファカウンタ)の値を見ています。
あ、その前にRSERR(受信エラー)のチェックをしていますが、実はそこはちょいと訳有りであることに気が付きましたので、説明は後回しにいたします。
BFCNTRが0ならそのままリターンします。
バッファに溜まっている受信データはありません。
BFCNTRが0でないならばバッファに未読データがありますから、バッファから1バイト読むとともに、BFCNTRの値を−1します。
前にも書きましたように、この受信バッファはリングバッファです。
最後のF8FFまでデータが埋まると、先頭のF800に戻って続きが書き込まれます。
そのままではどこが先頭でどこが最後のデータかわかりませんから、未読データの先頭のアドレスと最後のアドレス+1は、そのためのカウンタ(アドレスF900、F901)に維持されています。
バッファアドレスがF800〜F8FFというキリのよいアドレスに置かれているのは意図的にそうしたのです。
この場合、アドレスの上位8ビットは無視できますから、1バイトの数値で管理することができます。
そして、こちらが割込みプログラムです。
; rs232c int E5BA E5 RSINT:PUSH HL E5BB D5 PUSH DE E5BC C5 PUSH BC E5BD F5 PUSH AF E5BE ED DB ED;IN0 A,[04] E5BF 38 DB 38 E5C0 04 DB 04 E5C1 E670 AND 70 E5C3 C2E8E5 JP NZ,RSINTE E5C6 ED DB ED;IN0 D,[08] E5C7 10 DB 10 E5C8 08 DB 08 E5C9 3A02F9 LD A,(BFCNTR) E5CC 3C INC A E5CD CAE1E5 JP Z,RSINT2 E5D0 ED4B00F9 LD BC,(BFTOP) E5D4 2100F8 LD HL,SPTOP;=RSBF E5D7 68 LD L,B E5D8 72 LD (HL),D E5D9 04 INC B E5DA ED4300F9 LD (BFTOP),BC E5DE 3202F9 LD (BFCNTR),A E5E1 F1 RSINT2:POP AF E5E2 C1 POP BC E5E3 D1 POP DE E5E4 E1 POP HL E5E5 FB EI E5E6 ED4D RETI E5E8 3203F9 RSINTE:LD (RSERR),A E5EB F1 POP AF E5EC C1 POP BC E5ED D1 POP DE E5EE E1 POP HL E5EF ED4D RETI |