石原 博の覚書

電子工作に関する日々の覚書を記載します

KBC-Z11でソフトウエアUARTを使用してBASICを動かした

2021-12-27 21:08:20 | 日記

KBC-Z11でソフトウエアUARTを使用してBASICを動かした

デジット閉店セールで売られていたジャンク基板には、「KBC-Z84015EM」と「KBC-Z11」があった。前者については電脳伝説さんのサイト「https://vintagechips.wordpress.com/2021/06/08/kbc-z84015s/」で解説されておりBASICが動く。
ところが後者については、CPUがTMPZ84C011のためSIOが内蔵されておらず、シリアルによる入出力が簡単には出来ない。そこでソフトウエアによるシリアル入出力を行ない、BASICを動かしてみた。
KBC-Z84015EMに使用されているCPUであるTMPZ84C015はSIO,PIO,CTCを内蔵しているが、KBC-Z11に使われているTMPZ84C011は単純なパラレルの入出力(割り込みなし)とCTCだけである。このため工夫が必要となる。
シリアルの速度については9600baudとした。txdについては比較的単純で、startbit、bit0からbit7まで、stopbitの順で 1/9600 = 104uS ソフトウエアで遅延させながら出力されば良い。
問題なのはrxd。8bitマイクロコンピュータが全盛のころは、キーボードスキャンをCPUでデコードしているものも多かった。これはCPUに比較して非常に遅い人間がキーボードを押している時間内に、CPU主体で都合の良いときに読みに行く(ポーリング)というものである。ところがシリアルの入力については、たとえ五月雨式のキー入力であろうが、CPUの都合とは関係なく9600buadで突然送らられてくるわけでポーリングするわけには行かない。そこでCTCのカウンタモードを利用した割り込みでスタートビットをチェックし、その後はソフトウエアの遅延により約100uSec毎に読み取る仕組みとした。

 rxd----+-----para bit1(CN2 pin 34PA1)
          +-----CTC  (CN2 pin5 CLK/TRG0 )


===出力部プログラム(waitループのカウントについて試行錯誤で決めている)===
出力中は割り込みを停止している(ソフトウエアでwaitしているので割り込みはさせられない)ので、半二重といえる。

OUTCH: DI

PUSH AF
 IN A,(PPAD)
 AND 0FEH  ;START BIT
 OUT (PPAD),A
 CALL WAIT0
 POP AF
 PUSH DE
 PUSH BC
 LD B,8
OUTCH1: LD C,A
 AND 1  ;BIT0
 LD D,A
 IN A,(PPAD)
 AND 0FEH
 OR D
 OUT (PPAD),A
 CALL WAIT0
 LD A,C
 RRCA
 DEC B
 JP NZ,OUTCH1
 IN A,(PPAD)
 OR 1
 OUT (PPAD),A
 CALL WAIT0
 POP BC
 POP DE
 EI
 RET

WAIT0: PUSH BC
 LD B,37
WAIT1: DEC B
 JP NZ,WAIT1
 POP BC
 RET

出力波形(「H」055Hを出力した例)

===入力部プログラム===
本来ならストップビットまで確認し、フレーミングエラーをチェックすべきだが、もともとのSIOバージョンでもエラーチェックなしだし手を抜いた。

; 9600BAUD
INCH: CALL WAITS  ;SKIP START BIT(HALF)
 PUSH BC
 LD BC,0800H ;B=8,C=0
INCH1: CALL WAIT0
 IN A,(PPAD)
 AND 2
 RRCA
 OR C
 DEC B
 JP Z,INCH2
 RRCA
 LD C,A
 JP INCH1
INCH2: RRCA   ;B6,B5,B4,B3,B2,B1,B0,B7->B7..B0
 POP BC
 RET
;
WAITS: PUSH BC
 LD B,13
WAITS1: DEC B
 JP NZ,WAITS1
 POP BC
 RET

入力波形

最終的に電脳伝説さんのサイトにあるソースを以下のように変更し、動作させることが出来た。
(アセンブラはARCPIT XZ80.EXEとあったが見つからないため、CP/M上でSLR Z80を使用した)
=======================================
; MS-BASIC START UP ROUTINE
; TARGET: KBC-Z11
; ASSEMBLER: SLR Z80
;
TSTACK: EQU 80EDH
;
PCTCC0: EQU 10H
PPAC: EQU 54H
PPAD: EQU 50H
;
; SYSTEM PARAMETERS
 ORG 08000H
RBFCNT: DS 01H
RBFRDP: DS 01H
RBFWTP: DS 01H
RECBUF: DS 40H
;
;
; RESET VECTOR
 ORG 0000H
RST00: DI
 JP SINIT
;
; RESTART VECTOR
 ORG 0008H
RST08: JP TXA
 ORG 0010H
RST10: JP RXA
 ORG 0018H
RST18: JP KBHIT
;
; PORTA BIT1 -> BUFFER BY INTERRUPT
INTRCV:
 PUSH AF
 PUSH BC
 PUSH DE
 PUSH HL
 CALL INCH
 LD D,A  ;SAVE TO D
 LD A,(RBFCNT) ;GET COUNT
 CP 40H  ;IF BUFFER FULL
 JR Z,RWTEXT ;EXIT(GIVE UP!)
STRWT3: INC A  ;COUNT UP
 LD (RBFCNT),A ;COUNT UPDATE
 LD A,(RBFWTP) ;GET OFFSET
 LD C,A  ;C, OFFSET LOW
 LD B,00H  ;B, OFFSET HIGH
 LD HL,RECBUF ;HL, BUFFER TOP
 ADD HL,BC  ;HL, WRITE POINT IN BUFFER
 LD (HL),D  ;WRITE DATA
 INC A  ;OFFSET INCREMENT
 AND 3FH  ;WRAP
 LD (RBFWTP),A ;OFFSET UPDATE
RWTEXT: POP HL
 POP DE
 POP BC
 POP AF
 EI
 RETI
;
; BUFER -> A
RXA:
 PUSH BC
 PUSH DE
 PUSH HL
LOPRBR:
 LD A,(RBFCNT) ;GET COUNT
 AND A  ;CHECK RECEIVE
 JR Z,LOPRBR ;WAIT FOR RECEIVE
 DI   ;DISABLE INTERRUPT
 DEC A  ;COUNT DOWN
 LD (RBFCNT),A ;COUNT UPDATE
 LD A,(RBFRDP) ;GET OFFSET
 LD C,A  ;C, OFFSET LOW
 LD B,00H  ;B, OFFSET HIGH
 LD HL,RECBUF ;HL, BUFFER TOP
 ADD HL,BC  ;HL, READ POINT IN BUFFER
 LD D,(HL)  ;READ DATA
 INC A  ;OFFSET INCREMENT
 AND 3FH  ;WRAP
 LD (RBFRDP),A ;OFFSET UPDATE
 LD A,D  ;GET DATA
 POP HL
 POP DE
 POP BC
 EI   ;ENABLE INTERRUPT
 RET
;
; OUTCH
TXA: JP OUTCH
;
; CHECK RECEIVE STATUS
KBHIT: LD A,(RBFCNT)
 AND A
 RET
;
; INTERRUPT VECTORS
 ORG (($-1) & 0FFF0H) + 10H
INTVCT: DW INTRCV
;
; 9600BAUD
OUTCH: DI
 PUSH AF
 IN A,(PPAD)
 AND 0FEH  ;START BIT
 OUT (PPAD),A
 CALL WAIT0
 POP AF
 PUSH DE
 PUSH BC
 LD B,8
OUTCH1: LD C,A
 AND 1  ;BIT0
 LD D,A
 IN A,(PPAD)
 AND 0FEH
 OR D
 OUT (PPAD),A
 CALL WAIT0
 LD A,C
 RRCA
 DEC B
 JP NZ,OUTCH1
 IN A,(PPAD)
 OR 1
 OUT (PPAD),A
 CALL WAIT0
 POP BC
 POP DE
 EI
 RET
;
; 9600BAUD
INCH: CALL WAITS  ;SKIP START BIT(HALF)
 PUSH BC
 LD BC,0800H ;B=8,C=0
INCH1: CALL WAIT0
 IN A,(PPAD)
 AND 2
 RRCA
 OR C
 DEC B
 JP Z,INCH2
 RRCA
 LD C,A
 JP INCH1
INCH2: RRCA   ;B6,B5,B4,B3,B2,B1,B0,B7->B7..B0
 POP BC
 RET
;
WAIT0: PUSH BC
 LD B,37
WAIT1: DEC B
 JP NZ,WAIT1
 POP BC
 RET
;
WAITS: PUSH BC
 LD B,13
WAITS1: DEC B
 JP NZ,WAITS1
 POP BC
 RET
;
; SYSTEM INITIALIZE
SINIT: LD SP,TSTACK
 XOR A
 LD (RBFCNT),A
 LD (RBFRDP),A
 LD (RBFWTP),A
;
; CTC INITIALIZE
 LD A,11000111B ;COUNTER MODE
 OUT (PCTCC0),A
 LD A,1  ;COUNT=1
 OUT (PCTCC0),A
 LD A,INTVCT & 0FFH
 OUT (PCTCC0),A
;
; Z84C011 PORT I/O INITIALIZE
 LD A,00000001B
 OUT (PPAC),A ;PORT1=IN PORT0=OUT
 IN A,(PPAD)
 OR 1
 OUT (PPAD),A
;
; SETUP INTERRUPT
 LD A,(INTVCT SHR 8) AND 0FFH
 LD I,A
 IM 2
 EI
;
; START BASIC
 JP COLD
;
以降BASIC部分は変更なし。


基板上のLEDはPE5とPE6に接続されている。
===Lチカ例=======
10 OUT &H44,&H60
20 FOR I=0 TO 10
30 OUT &H40,0
40 FOR J=0 TO 100
50 NEXT J
60 OUT &H40,&H60
70 FOR J=0 TO 100
80 NEXT J
90 NEXT I