From d6829fd3d7227d278aa32049665897a8a1b2d0d5 Mon Sep 17 00:00:00 2001 From: Leo C Date: Wed, 17 Jun 2015 07:45:20 +0200 Subject: [PATCH 1/1] ascii.180 interrupt driver for ASCI 0/1 --- cbios/Makefile | 5 +- cbios/asci-cmn.180 | 113 +++++++ cbios/ascii.180 | 312 ++++++++++++++++++ cbios/ascip.180 | 107 +----- cbios/boot.180 | 2 +- cbios/conbuf.180 | 65 +--- cbios/fifo.180 | 143 +++++++++ cbios/gencpm.dat | 4 +- cbios/misc.180 | 432 ++++++++++++------------- cbios/mm.180 | 785 ++++++++++++++++++++++++--------------------- cbios/time.180 | 418 ++++++++++++------------ 11 files changed, 1443 insertions(+), 943 deletions(-) create mode 100644 cbios/asci-cmn.180 create mode 100644 cbios/ascii.180 create mode 100644 cbios/fifo.180 diff --git a/cbios/Makefile b/cbios/Makefile index 0c41e93..fafba28 100644 --- a/cbios/Makefile +++ b/cbios/Makefile @@ -1,8 +1,9 @@ SRC := bioskrnl.180 boot.180 chario.180 drvtbl.180 -SRC += move.180 time.180 mm.180 misc.180 utils.180 -SRC += msgbuf.180 conbuf.180 ascip.180 sdio.180 cfio.180 +SRC += move.180 time.180 mm.180 misc.180 utils.180 fifo.180 +SRC += msgbuf.180 conbuf.180 ascii.180 asci-cmn.180 +SRC += sdio.180 cfio.180 SRC += scb.180 ALLSRC := $(SRC) ldrbios.180 diff --git a/cbios/asci-cmn.180 b/cbios/asci-cmn.180 new file mode 100644 index 0000000..76ade5a --- /dev/null +++ b/cbios/asci-cmn.180 @@ -0,0 +1,113 @@ + + public as_init + + extrn ioiniml + extrn f_cpu,add_hla,div32_r + extrn @ctbl + + include config.inc + include z180reg.inc + + +;-------------------------------------------------------------- +; TC = (f PHI /(2*baudrate*Clock_mode)) - 2 +; +; Clock_mode == 16 +; TC = (f PHI / (32 * baudrate)) - 2 +; +; br150 = baudrate/150 +; TC = (f PHI / (32 * 150 * br150)) - 2 +; TC = (f PHI / (32 * 150 * br150)) - 2 + + +;-------------------------------------------------------------- +; Init Serial I/O for console input and output (ASCI1) +; +; b: device number (0..15) +; c: asci channel number (0/1) + + dseg +as_init: + ld hl,initab0 + dec c + jr nz,$+5 + ld hl,initab1 + + push hl + ld c,8 ; + mlt bc ; + ld hl,@ctbl+7 ;get baudrate index + add hl,bc ; + ld a,(hl) + and 0fh + add a,a ;get factor + ld hl,bd150_tab + call add_hla + ld c,(hl) + inc hl + ld b,(hl) + ld hl,(f_cpu) + ld de,(f_cpu+2) + call div32_r + ld bc,32*150 + call div32_r + ld de,2 + or a + sbc hl,de + jr nc,as_ini_1 + ld hl,0 +as_ini_1: + ld b,h + ld c,l + pop de + ld hl,init_br_off + add hl,de + ld (hl),c + inc hl + ld (hl),b + ex de,hl + jp ioiniml + + +bd150_tab: +; factor index baudrate orig. cp/m + dw 19200/150 ; 0 19200 - + dw 28800/150 ; 1 28800 50 + dw 38400/150 ; 2 38400 75 + dw 57600/150 ; 3 57600 110 + dw 11520/15 ; 4 115200 134.5 + dw 150/150 ; 5 150 + dw 300/150 ; 6 300 + dw 600/150 ; 7 600 + dw 1200/150 ; 8 1200 + dw 1800/150 ; 9 1800 + dw 2400/150 ;10 2400 + dw 3600/150 ;11 3600 + dw 4800/150 ;12 4800 + dw 7200/150 ;13 7200 + dw 9600/150 ;14 9600 + dw 19200/150 ;15 19200 + + + + +initab0: + db 1,stat0,0 ;Disable rx/tx interrupts + ;Enable baud rate generator + db 1,asext0,M_BRGMOD+M_DCD0DIS+M_CTS0DIS + db 2,astc0l +init_br_off equ $ - initab0 + dw 28 + db 1,cntlb0,M_MPBT ;No MP Mode, X16 + db 1,cntla0,M_RE+M_TE+M_MOD2 ;Rx/Tx enable, 8N1 + db 0 + +initab1: + db 1,stat1,0 ;Disable rx/tx ints, disable CTS1 + db 1,asext1,M_BRGMOD ;Enable baud rate generator + db 2,astc1l,low 3, high 3 + db 1,cntlb1,M_MPBT ;No MP Mode, X16 + db 1,cntla1,M_RE+M_TE+M_MOD2 ;Rx/Tx enable, 8N1 + db 0 + + end diff --git a/cbios/ascii.180 b/cbios/ascii.180 new file mode 100644 index 0000000..6bbf377 --- /dev/null +++ b/cbios/ascii.180 @@ -0,0 +1,312 @@ + page 200 + +; Interrupt drivers for ASCI0 and ASCI1 + + global as0init + global as0ista,as0inp + global as0osta,as0out + global as1init + global as1ista,as1inp + global as1osta,as1out + + extrn as_init + extrn ff_empty,ff_get,ff_full,ff_put + extrn bufinit + extrn isv_sw + + + + include config.inc + include z180reg.inc + + + +;----------------------------------------------------- + + dseg + + mkbuf s0.rx_id, s0.inbuf, s0.rx_len + mkbuf s0.tx_id, s0.outbuf,s0.tx_len + mkbuf s1.rx_id, s1.inbuf, s1.rx_len + mkbuf s1.tx_id, s1.outbuf, s1.tx_len + + + + dseg + +;-------------------------------------------------------------- +; Init Serial I/O for input and output (ASCI 0/1) +; +; b: device number +; + + +;ser.init: +; ld a,i +; push af ;save IFF +; di +;--- +; pop af +; ret po +; ei +; ret ; + +as0init: + xor a ; + out0 (stat0),a ;Disable rx/tx interrupts + ld c,0 ;asci channel number + call as_init + ld hl,rtxisvjmp0 ;rx/tx int vector + ld (ivtab + IV$ASCI0),hl ; + + ld ix,s0.inbuf + call bufinit + ld ix,s0.outbuf + call bufinit + ld a,M_RIE + out0 (stat0),a ;Enable rx interrupts + ret + +as1init: + xor a ; + out0 (stat1),a ;Disable rx/tx interrupts + ld c,1 ;asci channel number + call as_init + + ld hl,rtxisvjmp1 ;rx/tx int vector + ld (ivtab + IV$ASCI1),hl ; + + push ix + ld ix,s1.inbuf + call bufinit + ld ix,s1.outbuf + call bufinit + pop ix + ld a,M_RIE + out0 (stat1),a ;Enable rx interrupts + ret + + + cseg +rtxisvjmp0: + call isv_sw + dw rxtxi0 +rtxisvjmp1: + call isv_sw + dw rxtxi1 + +;-------------------------------------------------------------- + + dseg +as0ista: + push ix + ld ix,s0.inbuf ; + call ff_empty + pop ix + ret + +;-------------------------------------------------------------- + +as1ista: + push ix + ld ix,s1.inbuf ; + call ff_empty + pop ix + ret + +;-------------------------------------------------------------- +; Get an input character + +as0inp: + push ix + ld ix,s0.inbuf ; + call ff_get + pop ix + ret + +;-------------------------------------------------------------- +; Get an input character + +as1inp: + push ix + ld ix,s1.inbuf ; + call ff_get + pop ix + ret + +;-------------------------------------------------------------- +; Output status + +as0osta: + push ix + ld ix,s0.outbuf ; + call ff_full + pop ix + ret + +;-------------------------------------------------------------- +; Output status + +as1osta: + push ix + ld ix,s1.outbuf ; + call ff_full + pop ix + ret + +;-------------------------------------------------------------- +; put character in c in buffer +; destroys hl, bc +; returns output char in a + +as0out: + push ix ; + ld ix,s0.outbuf ; + call ff_put + di ; + in0 c,(stat0) ; + set TIE,c ; + out0 (stat0),c ; + ei ; + pop ix ; + ret + +;-------------------------------------------------------------- +; put character in c in buffer +; destroys hl, bc +; returns output char in a + +as1out: + push ix ; + ld ix,s1.outbuf ; + call ff_put + di ; + in0 c,(stat1) ; + set TIE,c ; + out0 (stat1),c ; + ei ; + pop ix ; + ret + + +;------------------------------------------ +; ASCI 1 Transmit/Receive interupt routines + + dseg +rxtxi0: + in0 e,(stat0) ;receive flag set? 5 + jp p,txisv0 ; + + in0 d,(rdr0) ;todo: break detection 9 + bit FE,e ;framing error? + jr nz,?0ri_1 + + push ix + ld ix,s0.inbuf ; + ld hl,s0.inbuf ; + ld c,(ix+o.in_idx) ; + ld b,0 + add hl,bc + ld (hl),d + + ld a,c ; + inc a + and (ix+o.mask) + cp (ix+o.out_idx) ; + jr z,$+5 ;skip if buffer is full + ld (ix+o.in_idx),a + pop ix +?0ri_1: + in0 a,(cntla0) ; 1 + res EFR,a ; + out0 (cntla0),a ; 1 + ret + +txisv0: + push ix + ld ix,s0.outbuf ; + + ld a,(ix+o.out_idx) ; + cp (ix+o.in_idx) ;if index.in == index.out + jr z,?0ti_2 ; buffer empty + + ld hl,s0.outbuf ; + ld c,a + ld b,0 + add hl,bc + ld l,(hl) + out0 (tdr0),l ; 7 + + inc a + and (ix+o.mask) + ld (ix+o.out_idx),a + jr ?0ti_3 +?0ti_2: + res TIE,e ;disable tx-int + out0 (stat0),e ; 5 +?0ti_3: + pop ix + ret + +;------------------------------------------ +; ASCI 1 Transmit/Receive interupt routines + + dseg +rxtxi1: + in0 e,(stat1) ;receive flag set? 5 + jp p,txisv1 ; + + in0 d,(rdr1) ;todo: break detection 9 + bit FE,e ;framing error? + jr nz,??ri_1 + + push ix + ld ix,s1.inbuf ; + ld hl,s1.inbuf ; + ld c,(ix+o.in_idx) ; + ld b,0 + add hl,bc + ld (hl),d + + ld a,c ; + inc a + and (ix+o.mask) + cp (ix+o.out_idx) ; + jr z,$+5 ;skip if buffer is full + ld (ix+o.in_idx),a + pop ix +??ri_1: + in0 a,(cntla1) ; 1 + res EFR,a ; + out0 (cntla1),a ; 1 + ret + +txisv1: + push ix + ld ix,s1.outbuf ; + + ld a,(ix+o.out_idx) ; + cp (ix+o.in_idx) ;if index.in == index.out + jr z,??ti_2 ; buffer empty + + ld hl,s1.outbuf ; + ld c,a + ld b,0 + add hl,bc + ld l,(hl) + out0 (tdr1),l ; 7 + + inc a + and (ix+o.mask) + ld (ix+o.out_idx),a + jr ??ti_3 +??ti_2: + res TIE,e ;disable tx-int + out0 (stat1),e ; 5 +??ti_3: + pop ix + ret + + + + end diff --git a/cbios/ascip.180 b/cbios/ascip.180 index 470c07e..0d68fd4 100644 --- a/cbios/ascip.180 +++ b/cbios/ascip.180 @@ -2,7 +2,6 @@ ; Simple polling drivers for ASCI0 and ASCI1 - extrn ioiniml global as0init global as0ista,as0inp @@ -11,120 +10,32 @@ global as1ista,as1inp global as1osta,as1out + extrn as_init - extrn f_cpu,add_hla,div32_r - extrn @ctbl include config.inc include z180reg.inc + dseg ;-------------------------------------------------------------- -; TC = (f PHI /(2*baudrate*Clock_mode)) - 2 +; Init Serial I/O for input and output (ASCI 0/1) ; -; Clock_mode == 16 -; TC = (f PHI / (32 * baudrate)) - 2 +; b: device number ; -; br150 = baudrate/150 -; TC = (f PHI / (32 * 150 * br150)) - 2 -; TC = (f PHI / (32 * 150 * br150)) - 2 -; -; Init Serial I/O for console input and output (ASCI1) -; - - dseg - as0init: - ld hl,initab0 - jr as_init + ld c,0 ;asci channel number + jp as_init + as1init: - ld hl,initab1 -as_init: - push hl - - ld c,8 ; - mlt bc ; - ld hl,@ctbl+7 ;get baudrate index - add hl,bc ; - ld a,(hl) - and 0fh - add a,a ;get factor - ld hl,bd150_tab - call add_hla - ld c,(hl) - inc hl - ld b,(hl) - ld hl,(f_cpu) - ld de,(f_cpu+2) - call div32_r - ld bc,32*150 - call div32_r - ld de,2 - or a - sbc hl,de - jr nc,as_ini_1 - ld hl,0 -as_ini_1: - ld b,h - ld c,l - pop de - ld hl,init_br_off - add hl,de - ld (hl),c - inc hl - ld (hl),b - ex de,hl - jp ioiniml - - -bd150_tab: -; factor index baudrate orig. cp/m - dw 19200/150 ; 0 19200 - - dw 28800/150 ; 1 28800 50 - dw 38400/150 ; 2 38400 75 - dw 57600/150 ; 3 57600 110 - dw 11520/15 ; 4 115200 134.5 - dw 150/150 ; 5 150 - dw 300/150 ; 6 300 - dw 600/150 ; 7 600 - dw 1200/150 ; 8 1200 - dw 1800/150 ; 9 1800 - dw 2400/150 ;10 2400 - dw 3600/150 ;11 3600 - dw 4800/150 ;12 4800 - dw 7200/150 ;13 7200 - dw 9600/150 ;14 9600 - dw 19200/150 ;15 19200 - - - - -initab0: - db 1,stat0,0 ;Disable rx/tx interrupts - ;Enable baud rate generator - db 1,asext0,M_BRGMOD+M_DCD0DIS+M_CTS0DIS - db 2,astc0l -init_br_off equ $ - initab0 - dw 28 - db 1,cntlb0,M_MPBT ;No MP Mode, X16 - db 1,cntla0,M_RE+M_TE+M_MOD2 ;Rx/Tx enable, 8N1 - db 0 - -initab1: - db 1,stat1,0 ;Disable rx/tx ints, disable CTS1 - db 1,asext1,M_BRGMOD ;Enable baud rate generator - db 2,astc1l,low 3, high 3 - db 1,cntlb1,M_MPBT ;No MP Mode, X16 - db 1,cntla1,M_RE+M_TE+M_MOD2 ;Rx/Tx enable, 8N1 - db 0 + ld c,1 ;asci channel number + jp as_init ;-------------------------------------------------------------- - dseg - as0ista: in0 a,(stat0) and M_RDRF diff --git a/cbios/boot.180 b/cbios/boot.180 index fcf00ae..766277f 100644 --- a/cbios/boot.180 +++ b/cbios/boot.180 @@ -54,6 +54,7 @@ hwini_skip: call cpu_frq ld (f_cpu),hl ld (f_cpu+2),de + call intinit ; setup interrupts and vectors ret ?init: @@ -68,7 +69,6 @@ hwini_skip: ld (@aovec),hl - call intinit ; setup interrupts and vectors call prt0ini ; init timer ei ld c,2 diff --git a/cbios/conbuf.180 b/cbios/conbuf.180 index 75741e0..3c846dd 100644 --- a/cbios/conbuf.180 +++ b/cbios/conbuf.180 @@ -6,6 +6,7 @@ ; global ff.init,ff.in,ff.ist,ff.out,ff.ost + extrn ff_empty,ff_get,ff_full,ff_put extrn bufinit,fifolst include config.inc @@ -38,65 +39,33 @@ ff.init: ;-------------------------------------------------------------- ; Input status -; buffer is empty, if output index and input index are the same dseg ff.ist: push ix ld ix,(fifolst+ici) ; - -buf.empty: - ld a,(ix+o.in_idx) ; - sub (ix+o.out_idx) ; + call ff_empty pop ix - ret z - or 0ffh ret - ;-------------------------------------------------------------- -; Output status -; buffer is full, if output index is one behind input index +; Get an input character ff.in: push ix ld ix,(fifolst+ici) ; - -buf.get: - push ix - pop hl - ld c,(ix+o.out_idx) ; - ld b,0 - add hl,bc - ld a,c -bg.wait: - cp (ix+o.in_idx) ; - jr z,bg.wait - ld b,(hl) - ld a,c ; - inc a - and (ix+o.mask) - ld (ix+o.out_idx),a - ld a,b + call ff_get pop ix ret ;-------------------------------------------------------------- ; Output status -; buffer is full, if output index is one behind input index ff.ost: push ix ld ix,(fifolst+ico) ; - -buf.full: - ld a,(ix+o.in_idx) ; - inc a - and (ix+o.mask) - sub (ix+o.out_idx) ; + call ff_full pop ix - ret z - or 0ffh ret @@ -108,28 +77,10 @@ buf.full: ff.out: push ix ; ld ix,(fifolst+ico) ; -buf.put: - push ix ; - pop hl ; get buffer start address - - ld a,c ; - ld c,(ix+o.in_idx) ; add input index - ld b,0 ; - add hl,bc ; - ld (hl),a ; one place is allways free - ld b,a ; - - ld a,c ; bump input index - inc a ; - and (ix+o.mask) ; -bp.wait: ; do - cp (ix+o.out_idx) ; - jr z,bp.wait ; while new input idx == ouput idx - ld (ix+o.in_idx),a ; - + call ff_put out (AVRINT6),a ; tell monitor - ld a,b ; pop ix ; - ret ; + ret end + diff --git a/cbios/fifo.180 b/cbios/fifo.180 new file mode 100644 index 0000000..341b5c7 --- /dev/null +++ b/cbios/fifo.180 @@ -0,0 +1,143 @@ + + public bufinit + public ff_empty,ff_get,ff_full,ff_put + + public fifolst + + extrn msg.sm,hwl2phy + + include config.inc + include z180reg.inc + + +;-------------------------------------------------------------------- + + dseg + +fifolst: + rept 4 + dw 0 + endm + +;-------------------------------------------------------------------- + + dseg + +bufinit: + ld (ix+o.in_idx),0 ;reset pointers (empty fifo) + ld (ix+o.out_idx),0 + ld a,(ix+o.id) + ld hl,fifolst + ld e,a + ld d,0 + add hl,de + add hl,de + push ix + pop de + cp 4 + jr nc,bfi_skip + + ld (hl),e + inc hl + ld (hl),d + +bfi_skip: + ex de,hl + call hwl2phy ;get phys. address of fifo + ld c,a + ld a,(ix+o.id) ;fifo id + or a ;test if fifo 0 + ret z + + cp 4 + ret nc + +; TODO: move to better place + + ld b,a + push bc ;c: bank-addr, b: ignored + push hl ;address + ld c,0 + push bc ;c: function, b:subf + ld b,5 + ld h,c + ld l,c + add hl,sp + call msg.sm + pop hl + pop hl + pop hl + ret + +;-------------------------------------------------------------- +; Check if characters in fifo +; Fifo is empty, if output index and input index are the same + +ff_empty: + ld a,(ix+o.in_idx) ; + sub (ix+o.out_idx) ; + ret z + or 0ffh + ret + +;-------------------------------------------------------------- + +ff_get: + push ix + pop hl + ld c,(ix+o.out_idx) ; + ld b,0 + add hl,bc + ld a,c +bg.wait: + cp (ix+o.in_idx) ; + jr z,bg.wait + ld b,(hl) + ld a,c ; + inc a + and (ix+o.mask) + ld (ix+o.out_idx),a + ld a,b + ret + +;-------------------------------------------------------------- +; Check if room in fifo +; buffer is full, if output index is one behind input index + +ff_full: + ld a,(ix+o.in_idx) ; + inc a + and (ix+o.mask) + sub (ix+o.out_idx) ; + ret z + or 0ffh + ret + + +;-------------------------------------------------------------- +; put character in c in buffer +; destroys hl, bc +; returns output char in a + +ff_put: + push ix ; + pop hl ; get buffer start address + + ld a,c ; + ld c,(ix+o.in_idx) ; add input index + ld b,0 ; + add hl,bc ; + ld (hl),a ; one place is allways free + ld b,a ; + + ld a,c ; bump input index + inc a ; + and (ix+o.mask) ; +bp.wait: ; do + cp (ix+o.out_idx) ; + jr z,bp.wait ; while new input idx == ouput idx + ld (ix+o.in_idx),a ; + ld a,b ; + ret ; + + end diff --git a/cbios/gencpm.dat b/cbios/gencpm.dat index 408b8e8..874b2b1 100644 --- a/cbios/gencpm.dat +++ b/cbios/gencpm.dat @@ -4,7 +4,7 @@ PAGLEN = 17 BACKSPC = N RUBOUT = N BOOTDRV = A -MEMTOP = FE +MEMTOP = FD BNKSWT = Y COMBAS = F0 LERROR = Y @@ -155,4 +155,4 @@ OVLYDTAO = Y OVLYDTAP = Y CRDATAF = N DBLALV = Y - \ No newline at end of file + diff --git a/cbios/misc.180 b/cbios/misc.180 index 28c0123..d39f632 100644 --- a/cbios/misc.180 +++ b/cbios/misc.180 @@ -1,216 +1,216 @@ - - public intinit - public bufinit - public cpu_frq - public get_tmr - - public fifolst - - extrn div32_r,?pmsg - extrn msg.sm,msg.recv,hwl2phy - - include config.inc - include z180reg.inc - - -;---------------------------------------------------------------------- - - dseg - -intinit: - ld hl,ivtab ; - ld a,h ; - ld i,a ; - out0 (il),l ; - im 2 - -; Let all vectors point to spurious int routines. - - ld de,sp.int0 - ld bc,sp.int.len - ld a,9 -ivt_i1: - ld (hl),e - inc l - ld (hl),d - inc l - ex de,hl - add hl,bc - ex de,hl - dec a - jr nz,ivt_i1 - ret - - -;-------------------------------------------------------------------- -; Spurious interrupt handler - - cseg ; common area -sp.int0: - ld a,00h - jr sp.i.1 -sp.int.len equ $-sp.int0 - ld a,01h - jr sp.i.1 - ld a,02h - jr sp.i.1 - ld a,03h - jr sp.i.1 - ld a,04h - jr sp.i.1 - ld a,05h - jr sp.i.1 - ld a,06h - jr sp.i.1 - ld a,07h - jr sp.i.1 - ld a,08h -sp.i.1: -; out (80h),a - - add a,'0' - ld (spi$nr),a - ld hl,spi$msg - call ?pmsg -sp.i.2: - halt - jr sp.i.2 - -spi$msg: - db 13,10,'Spurious Int: ' -spi$nr: db '0' - db 0 - -;-------------------------------------------------------------------- -; -; Get/compute CPU clock -; -; return: -; hlde: CPU frequency (Hz) -; - - dseg - -cpu_frq: - ld hl,0 - ld d,h - ld e,l - call get_tmr - push de - push hl - -; delay ~8ms @ 18.432MHz --> 147456 clock cycles -; delay ~10ms @ 18.432MHz --> 184320 clock cycles -; - -; ld hl,8192 ; 147456/18 - ld hl,(10240-100)*5 ; 184320/18 - ld de,1 - or a -dly_lp: - sbc hl,de ; 10 - jr nz,dly_lp ; 6/8 -> 18 cycles - - pop hl - pop de - call get_tmr - - ld b,h - ld c,l - ld de,036EEh ;18432000/(2**16) * 50 - ld hl,08000h ;18432000%(2**16) * 50 - - ld a,b - or a - jr nz,cpuf_div - ld a,c - cp 2 - jr c,cpuf_done -cpuf_div: - call div32_r -cpuf_done: - ret - -;-------------------------------------------------------------------- - - dseg -get_tmr: - push de - push hl - ld hl,1*256 + 3 ; h = subcommand, l = command - push hl - ld hl,0 - add hl,sp - ld b,6 - call msg.sm - - dec sp - ld hl,0 - add hl,sp - ld b,7 ; max receive message len - call msg.recv - - pop bc - inc sp - pop hl - pop de - ret - -;-------------------------------------------------------------------- - - dseg - -fifolst: - rept 4 - dw 0 - endm - -;-------------------------------------------------------------------- - - dseg - -bufinit: - ld (ix+o.in_idx),0 ;reset pointers (empty fifo) - ld (ix+o.out_idx),0 - ld a,(ix+o.id) - ld hl,fifolst - ld e,a - ld d,0 - add hl,de - add hl,de - push ix - pop de - cp 4 - jr nc,bfi_skip - - ld (hl),e - inc hl - ld (hl),d - -bfi_skip: - ex de,hl - call hwl2phy ;get phys. address of fifo - ld c,a - ld a,(ix+o.id) ;fifo id - or a ;test if fifo 0 - ret z - - ld b,a - push bc ;c: bank-addr, b: ignored - push hl ;address - ld c,0 - push bc ;c: function, b:subf - ld b,5 - ld h,c - ld l,c - add hl,sp - call msg.sm - pop hl - pop hl - pop hl - ret - -;---------------------------------------------------------------------- - - - end + + public intinit + public bufinit + public cpu_frq + public get_tmr + + public fifolst + + extrn div32_r,?pmsg + extrn msg.sm,msg.recv,hwl2phy + + include config.inc + include z180reg.inc + + +;---------------------------------------------------------------------- + + dseg + +intinit: + ld hl,ivtab ; + ld a,h ; + ld i,a ; + out0 (il),l ; + im 2 + +; Let all vectors point to spurious int routines. + + ld de,sp.int0 + ld bc,sp.int.len + ld a,9 +ivt_i1: + ld (hl),e + inc l + ld (hl),d + inc l + ex de,hl + add hl,bc + ex de,hl + dec a + jr nz,ivt_i1 + ret + + +;-------------------------------------------------------------------- +; Spurious interrupt handler + + cseg ; common area +sp.int0: + ld a,00h + jr sp.i.1 +sp.int.len equ $-sp.int0 + ld a,01h + jr sp.i.1 + ld a,02h + jr sp.i.1 + ld a,03h + jr sp.i.1 + ld a,04h + jr sp.i.1 + ld a,05h + jr sp.i.1 + ld a,06h + jr sp.i.1 + ld a,07h + jr sp.i.1 + ld a,08h +sp.i.1: +; out (80h),a + + add a,'0' + ld (spi$nr),a + ld hl,spi$msg + call ?pmsg +sp.i.2: + halt + jr sp.i.2 + +spi$msg: + db 13,10,'Spurious Int: ' +spi$nr: db '0' + db 0 + +;-------------------------------------------------------------------- +; +; Get/compute CPU clock +; +; return: +; hlde: CPU frequency (Hz) +; + + dseg + +cpu_frq: + ld hl,0 + ld d,h + ld e,l + call get_tmr + push de + push hl + +; delay ~8ms @ 18.432MHz --> 147456 clock cycles +; delay ~10ms @ 18.432MHz --> 184320 clock cycles +; + +; ld hl,8192 ; 147456/18 + ld hl,(10240-100)*5 ; 184320/18 + ld de,1 + or a +dly_lp: + sbc hl,de ; 10 + jr nz,dly_lp ; 6/8 -> 18 cycles + + pop hl + pop de + call get_tmr + + ld b,h + ld c,l + ld de,036EEh ;18432000/(2**16) * 50 + ld hl,08000h ;18432000%(2**16) * 50 + + ld a,b + or a + jr nz,cpuf_div + ld a,c + cp 2 + jr c,cpuf_done +cpuf_div: + call div32_r +cpuf_done: + ret + +;-------------------------------------------------------------------- + + dseg +get_tmr: + push de + push hl + ld hl,1*256 + 3 ; h = subcommand, l = command + push hl + ld hl,0 + add hl,sp + ld b,6 + call msg.sm + + dec sp + ld hl,0 + add hl,sp + ld b,7 ; max receive message len + call msg.recv + + pop bc + inc sp + pop hl + pop de + ret + +;-------------------------------------------------------------------- + + dseg + +fifolst: + rept 4 + dw 0 + endm + +;-------------------------------------------------------------------- + + dseg + +bufinit: + ld (ix+o.in_idx),0 ;reset pointers (empty fifo) + ld (ix+o.out_idx),0 + ld a,(ix+o.id) + ld hl,fifolst + ld e,a + ld d,0 + add hl,de + add hl,de + push ix + pop de + cp 4 + jr nc,bfi_skip + + ld (hl),e + inc hl + ld (hl),d + +bfi_skip: + ex de,hl + call hwl2phy ;get phys. address of fifo + ld c,a + ld a,(ix+o.id) ;fifo id + or a ;test if fifo 0 + ret z + + ld b,a + push bc ;c: bank-addr, b: ignored + push hl ;address + ld c,0 + push bc ;c: function, b:subf + ld b,5 + ld h,c + ld l,c + add hl,sp + call msg.sm + pop hl + pop hl + pop hl + ret + +;---------------------------------------------------------------------- + + + end diff --git a/cbios/mm.180 b/cbios/mm.180 index b4e6f61..9f90e03 100644 --- a/cbios/mm.180 +++ b/cbios/mm.180 @@ -1,359 +1,426 @@ - page 255 - .z80 - - - global mmuinit - global bnk2log,bnk2phy,hwl2phy,phy2log - - include config.inc - include z180reg.inc - - -;---------------------------------------------------------------------- -; Memory Map 1: -; -; Common CAStart .. 0FFFF -; Bank 0 00000 .. CAStart-1 -; Bank 1 10000 .. -; Bank 2 -; -; Memory Map 2: -; -; Common 18000 .. 1BFFF BANK1 -; -; Bank 0 00000 .. 0BFFF 0 -; Bank 1 0C000 .. 17FFF 1*BNK_SIZE -; Bank 2 1C000 .. 27FFF 2*BNK_SIZE + CMN_SIZE -; Bank 3 28000 .. 33FFF 3*BNK_SIZE + CMN_SIZE -; Bank n n*BNK_SIZE + (n < 2) ? 0 : CMN_SIZE -; -;---------------------------------------------------------------------- - - cseg - -mmuinit: - ld a,USR$CBAR - out0 (cbar),a - ret - -;-------------------------------------------------------------------- -; Return the BBR value for the given bank number -; -; in a: Bank number -; out a: bbr value - - if 0 ; Memory Map 1 - -bnk2log: - or a ; - ret z ; Bank 0 is at physical address 0 - - dec a ; - push bc ; - ld c,a ; - ld b,BNK_SIZE ; - mlt bc ; bank size * bank number - ld a,c ; - add a,10h ; add bank0 + common - pop bc ; - ret ; - - else ; Memory Map 2 - -bnk2log: - or a - ret z ; Bank 0 is at physical address 0 - - push bc - ld c,a ; - ld b,BNK_SIZE ; - mlt bc ; bank size * bank number - cp 2 ; - ld a,c ; - pop bc - ret c - add a,CMN_SIZE - ret - - endif - - if 0 ; table version - - push hl - ld hl,bnk_table ; - add a,l ; - ld l,a ; - jr nc,$+3 ; - inc h ; - ld a,(hl) ; - pop hl - ret - - endif - -;-------------------------------------------------------------- - -;in hl: Log. Address -; a: Bank number -; -;out ahl: Phys. (linear) Address - - -bnk2phy: - push bc - ld c,a - ld a,h - and a,0f0h - cp CA*16 - ld a,c - pop bc - jr c,b2p_banked - ; address is in common - if 0 ; Memory Map 1 - ld a,0 ; base is 0 - else ; Memory Map 2 - ld a,1 ; same as bank1 - endif - -b2p_banked: - call bnk2log ; get address base - - ; fall thru - -;-------------------------------------------------------------- -; -; hl: Log. Address -; a: Bank base (bbr) -; -; 2 0 0 -; 0 6 8 0 -; hl hhhhhhhhllllllll -; a + bbbbbbbb -; -; OP: ahl = (a<<12) + (h<<8) + l -; -;out ahl: Phys. (linear) Address - -log2phy: - push bc ; -l2p_i: - ld c,a ; - ld b,16 ; - mlt bc ; bc = a<<4 - ld a,c ; - add a,h ; - ld h,a ; - ld a,b ; - adc a,0 ; - pop bc ; - ret ; - -;-------------------------------------------------------------- -; -; hl: Log. Address -; -; -; OP: ahl = (bankbase<<12) + (h<<8) + l -; -;out ahl: Phys. (linear) Address - - -hwl2phy: - push bc ; - in0 c,(cbar) ; - ld a,h ; - or 00fh ; log. addr in common1? - cp c - jr c,hlp_1 - - in0 a,(cbr) ; yes, cbr is address base - jr hl2p_x -hlp_1: - ld b,16 ; log. address in baked area? - mlt bc - ld a,h - cp c - jr c,hlp_2 - in0 a,(bbr) ; yes, bbr is address base - jr hl2p_x -hlp_2: - xor a ; common1 -hl2p_x: - jr nz,l2p_i - - pop bc ; bank part is 0, no translation - ret ; - - -;-------------------------------------------------------------- -; return logical bank 0 address for given physical address. -; -; in: ahl: pyhsical addres (20 bit) -; out hl: logical address. -; logical address is in bank 0 or common, no bank number returned -; - -phy2log: - or a - ret z - - push bc - push hl - ld l,h - ld h,0 - ld bc,-16*SYS$CBR - add hl,bc - ld h,l - pop bc - ld l,c - pop bc - ret - -;-------------------------------------------------------------- -; Trampoline for routines in banked ram. -; Switch stack pointer to "system" stack in top ram -; Save cbar -; - extrn bs$stack - - cseg ; common! - - public _b0call -_b0call: - push af - in0 a,(bbr) - jr nz,b0c_doit - pop af - - ex (sp),hl ;16 - push de - ld e,(hl) - inc hl - ld d,(hl) - inc hl - ld (b0c_fast_go),de - pop de - ex (sp),hl ;16 -b0c_fast_go equ $+1 - jp 0 - -b0c_doit: - ld (b0_save_hl),hl - ld (b0_save_de),de - pop hl - ld (b0_save_af),hl - - pop de ;get ptr to 'function address' in de - ld hl,2 - add hl,de - push hl ;put return address on stack - - if 0 ; link80 - - ld hl,0 - add hl,sp ; - ld a,h - cp high (bs$stack-bs$stack$size) ;link80 can't process this - jr nc,$ + 5 ;skip if stack allready in common bios ram - - else - - ld hl,bs$stack-bs$stack$size - ld a,h - dec a - ld hl,0 - add hl,sp ; - cp h - jr c,$ + 5 ;skip if stack allready in common bios ram - endif - ld sp,bs$stack ; - - push hl ;save user stack pointer - - in0 h,(bbr) ; - push hl ; - ld hl,b0c_ret - push hl - xor a - out0 (bbr),a ; - ex de,hl ;ptr - ld e,(hl) ;get 'function address' - inc hl ; - ld d,(hl) ; - push de ;put on (switched) stack - - ld hl,(b0_save_af) ;get back users registers - push hl - pop af - ld de,(b0_save_de) - ld hl,(b0_save_hl) - ret ;go to function -b0c_ret: - ld (b0_save_hl),hl - - pop hl ; - out0 (bbr),h ; - pop hl ; - ld sp,hl ; - ld hl,(b0_save_hl) - ret ; - - -b0_save_hl: dw 0 -b0_save_de: dw 0 -b0_save_af: dw 0 - - - -;==================================================================== - - if 0 - -;-------------------------------------------------------------------- -; Return the BBR value for the given bank number - -bnk2bbr: - or a ; 4 - ret z ; 5/10 | 11 14 - - push bc ;11 | 11 - ld b,a ; 4 - ld c,CA ; 6 - mlt bc ;17 >45 - ld a,c ; 4 - add a,10h ; 6 - pop bc ; 9 | 10 - ret ; 9 | 10 76 - - push ix ;2 / 14 | 15 - ld ix,bnktbl ;4 / 12 | 14 - ld ($+3+2),a ;3 / 15 | 19 - ld a,(ix+0) ;3 / 14 | 19 - pop ix ;2 / 12 | 14 - ret ;1 / 9 | 10 15 / 76|91 - - push hl ;1 / 11 | 11 - ld hl,bnktbl ;3 / 9 | 10 - add a,l ;1 / 4 | 4 - ld l,a ;1 / 4 | 4 - ld a,0 ;1 / 6 | 7 - adc a,h ;1 / 4 | 4 - ld h,a ;1 / 4 | 4 - ld a,(hl) ;1 / 6 | 7 - pop hl ;1 / 9 | 10 - ret ;1 / 9 | 10 12 / 66|71 - - push hl ;1 / 11 | 11 - add a,low bnktbl ;2 / 6 | 7 - ld l,a ;1 / 4 | 4 - ld a,0 ;1 / 6 | 7 - adc a,high bnktbl ;2 / 6 | 7 - ld h,a ;1 / 4 | 4 - ld a,(hl) ;1 / 6 | 7 - pop hl ;1 / 9 | 10 - ret ;1 / 9 | 10 11 / 61|67 - - endif - - - end + page 255 + .z80 + + + public mmuinit + public bnk2log,bnk2phy,hwl2phy,phy2log + public isv_sw + + include config.inc + include z180reg.inc + + +;---------------------------------------------------------------------- +; Memory Map 1: +; +; Common CAStart .. 0FFFF +; Bank 0 00000 .. CAStart-1 +; Bank 1 10000 .. +; Bank 2 +; +; Memory Map 2: +; +; Common 18000 .. 1BFFF BANK1 +; +; Bank 0 00000 .. 0BFFF 0 +; Bank 1 0C000 .. 17FFF 1*BNK_SIZE +; Bank 2 1C000 .. 27FFF 2*BNK_SIZE + CMN_SIZE +; Bank 3 28000 .. 33FFF 3*BNK_SIZE + CMN_SIZE +; Bank n n*BNK_SIZE + (n < 2) ? 0 : CMN_SIZE +; +;---------------------------------------------------------------------- + + cseg + +mmuinit: + ld a,USR$CBAR + out0 (cbar),a + ret + +;-------------------------------------------------------------------- +; Return the BBR value for the given bank number +; +; in a: Bank number +; out a: bbr value + + if 0 ; Memory Map 1 + +bnk2log: + or a ; + ret z ; Bank 0 is at physical address 0 + + dec a ; + push bc ; + ld c,a ; + ld b,BNK_SIZE ; + mlt bc ; bank size * bank number + ld a,c ; + add a,10h ; add bank0 + common + pop bc ; + ret ; + + else ; Memory Map 2 + +bnk2log: + or a + ret z ; Bank 0 is at physical address 0 + + push bc + ld c,a ; + ld b,BNK_SIZE ; + mlt bc ; bank size * bank number + cp 2 ; + ld a,c ; + pop bc + ret c + add a,CMN_SIZE + ret + + endif + + if 0 ; table version + + push hl + ld hl,bnk_table ; + add a,l ; + ld l,a ; + jr nc,$+3 ; + inc h ; + ld a,(hl) ; + pop hl + ret + + endif + +;-------------------------------------------------------------- + +;in hl: Log. Address +; a: Bank number +; +;out ahl: Phys. (linear) Address + + +bnk2phy: + push bc + ld c,a + ld a,h + and a,0f0h + cp CA*16 + ld a,c + pop bc + jr c,b2p_banked + ; address is in common + if 0 ; Memory Map 1 + ld a,0 ; base is 0 + else ; Memory Map 2 + ld a,1 ; same as bank1 + endif + +b2p_banked: + call bnk2log ; get address base + + ; fall thru + +;-------------------------------------------------------------- +; +; hl: Log. Address +; a: Bank base (bbr) +; +; 2 0 0 +; 0 6 8 0 +; hl hhhhhhhhllllllll +; a + bbbbbbbb +; +; OP: ahl = (a<<12) + (h<<8) + l +; +;out ahl: Phys. (linear) Address + +log2phy: + push bc ; +l2p_i: + ld c,a ; + ld b,16 ; + mlt bc ; bc = a<<4 + ld a,c ; + add a,h ; + ld h,a ; + ld a,b ; + adc a,0 ; + pop bc ; + ret ; + +;-------------------------------------------------------------- +; +; hl: Log. Address +; +; +; OP: ahl = (bankbase<<12) + (h<<8) + l +; +;out ahl: Phys. (linear) Address + + +hwl2phy: + push bc ; + in0 c,(cbar) ; + ld a,h ; + or 00fh ; log. addr in common1? + cp c + jr c,hlp_1 + + in0 a,(cbr) ; yes, cbr is address base + jr hl2p_x +hlp_1: + ld b,16 ; log. address in baked area? + mlt bc + ld a,h + cp c + jr c,hlp_2 + in0 a,(bbr) ; yes, bbr is address base + jr hl2p_x +hlp_2: + xor a ; common1 +hl2p_x: + jr nz,l2p_i + + pop bc ; bank part is 0, no translation + ret ; + + +;-------------------------------------------------------------- +; return logical bank 0 address for given physical address. +; +; in: ahl: pyhsical addres (20 bit) +; out hl: logical address. +; logical address is in bank 0 or common, no bank number returned +; + +phy2log: + or a + ret z + + push bc + push hl + ld l,h + ld h,0 + ld bc,-16*SYS$CBR + add hl,bc + ld h,l + pop bc + ld l,c + pop bc + ret + +;-------------------------------------------------------------- +; Trampoline for routines in banked ram. +; Switch stack pointer to "system" stack in top ram +; Save cbar +; + extrn bs$stack + + cseg ; common! + + public _b0call +_b0call: + push af + in0 a,(bbr) + jr nz,b0c_doit + pop af + + ex (sp),hl ;16 + push de + ld e,(hl) + inc hl + ld d,(hl) + inc hl + ld (b0c_fast_go),de + pop de + ex (sp),hl ;16 +b0c_fast_go equ $+1 + jp 0 + +b0c_doit: + ld (b0_save_hl),hl + ld (b0_save_de),de + pop hl + ld (b0_save_af),hl + + pop de ;get ptr to 'function address' in de + ld hl,2 + add hl,de + push hl ;put return address on stack + + if 0 ; link80 + + ld hl,0 + add hl,sp ; + ld a,h + cp high (bs$stack-bs$stack$size) ;link80 can't process this + jr nc,$ + 5 ;skip if stack allready in common bios ram + + else + + ld hl,bs$stack-bs$stack$size + ld a,h + dec a + ld hl,0 + add hl,sp ; + cp h + jr c,$ + 5 ;skip if stack allready in common bios ram + endif + ld sp,bs$stack ; + + push hl ;save user stack pointer + + in0 h,(bbr) ; + push hl ; + ld hl,b0c_ret + push hl + xor a + out0 (bbr),a ; + ex de,hl ;ptr + ld e,(hl) ;get 'function address' + inc hl ; + ld d,(hl) ; + push de ;put on (switched) stack + + ld hl,(b0_save_af) ;get back users registers + push hl + pop af + ld de,(b0_save_de) + ld hl,(b0_save_hl) + ret ;go to function +b0c_ret: + ld (b0_save_hl),hl + + pop hl ; + out0 (bbr),h ; + pop hl ; + ld sp,hl ; + ld hl,(b0_save_hl) + ret ; + + +b0_save_hl: dw 0 +b0_save_de: dw 0 +b0_save_af: dw 0 + + +;-------------------------------------------------------------------- +; Trampoline for interrupt routines in banked ram. +; Switch stack pointer to "system" stack in top ram +; Save bbr + + cseg +isv_sw: ; + ex (sp),hl ;save hl, 'return adr' in hl + push de ; + push af ; + ex de,hl ;'return address' in de + + if 0 + if 0 ; link80 + + ld hl,0 + add hl,sp ; + ld a,h + cp high (bs$stack-bs$stack$size) ;link80 can't process this + jr nc,$ + 5 ;skip if stack allready in common bios ram + + else + + ld hl,bs$stack-bs$stack$size + ld a,h + dec a + ld hl,0 + add hl,sp ; + cp h + jr c,$ + 5 ;skip if stack allready in common bios ram + endif + ld sp,bs$stack ; + else + ld hl,0 + add hl,sp + ld sp,istack + endif + push hl ;save user stack pointer + in0 h,(bbr) ; + push hl ; + xor a ; + out0 (bbr),a ; + ex de,hl ; + ld e,(hl) ; + inc hl ; + ld d,(hl) ; + ex de,hl ; + push bc ; + call jphl ; + + pop bc ; + pop hl ; + out0 (bbr),h ; + pop hl ; + ld sp,hl ; + pop af ; + pop de ; + pop hl ; + ei ; + ret ; +jphl: + jp (hl) ; + + + ds 24 +istack: + +;==================================================================== + + if 0 + +;-------------------------------------------------------------------- +; Return the BBR value for the given bank number + +bnk2bbr: + or a ; 4 + ret z ; 5/10 | 11 14 + + push bc ;11 | 11 + ld b,a ; 4 + ld c,CA ; 6 + mlt bc ;17 >45 + ld a,c ; 4 + add a,10h ; 6 + pop bc ; 9 | 10 + ret ; 9 | 10 76 + + push ix ;2 / 14 | 15 + ld ix,bnktbl ;4 / 12 | 14 + ld ($+3+2),a ;3 / 15 | 19 + ld a,(ix+0) ;3 / 14 | 19 + pop ix ;2 / 12 | 14 + ret ;1 / 9 | 10 15 / 76|91 + + push hl ;1 / 11 | 11 + ld hl,bnktbl ;3 / 9 | 10 + add a,l ;1 / 4 | 4 + ld l,a ;1 / 4 | 4 + ld a,0 ;1 / 6 | 7 + adc a,h ;1 / 4 | 4 + ld h,a ;1 / 4 | 4 + ld a,(hl) ;1 / 6 | 7 + pop hl ;1 / 9 | 10 + ret ;1 / 9 | 10 12 / 66|71 + + push hl ;1 / 11 | 11 + add a,low bnktbl ;2 / 6 | 7 + ld l,a ;1 / 4 | 4 + ld a,0 ;1 / 6 | 7 + adc a,high bnktbl ;2 / 6 | 7 + ld h,a ;1 / 4 | 4 + ld a,(hl) ;1 / 6 | 7 + pop hl ;1 / 9 | 10 + ret ;1 / 9 | 10 11 / 61|67 + + endif + + + end diff --git a/cbios/time.180 b/cbios/time.180 index 2eb8123..befd0ec 100644 --- a/cbios/time.180 +++ b/cbios/time.180 @@ -1,208 +1,210 @@ - title 'Time module for the Modular CP/M 3 BIOS' - - public ?time, gs_rtc - public prt0ini - public gtimer,gstimer - - extrn @date,@hour,@min,@sec - extrn f_cpu - extrn ioiniml,div32_16 - extrn msg.sm,msg.recv - extrn _b0call - - include config.inc - include z180reg.inc - - -;---------------------------------------------------------------------- -; c == 00h: get time -; c == ffh: set time - - cseg ; time must be done from resident memory -?time: - inc c ;zero if ff - ld c,3 - jr z,time_set - - ld a,(time_to) - or a - ret nz - - dec c -time_set: - b0call gs_rtc - ld a,0ffh - ld (time_to),a - ret - -;---------------------------------------------------------------------- -; c = 2: get time -; c = 3: set time - - dseg -gs_rtc: - - push hl - push de - - ld hl,(@date) - ld a,(@hour) - ld d,a - ld a,(@min) - ld e,a - ld a,(@sec) - ld b,a ;b = sec, c = subcommand - push hl ;2 - push de ;4 - push bc ;6 - ld hl,3 * 256 + 0 ;h = command, l = 0 - push hl ;8 - - ld h,l ;hl = 0 - add hl,sp - push hl - inc hl ;7 - - ld b,7 - call msg.sm - - pop hl ;8 - ld b,8 ; max receive message len - call msg.recv - - pop hl ;len/command (discard) - pop bc ;subc/sec - pop de - pop hl - ld a,b - ld (@sec),a - ld a,e - ld (@min),a - ld a,d - ld (@hour),a - ld (@date),hl - - pop de - pop hl - ret - -;---------------------------------------------------------------------- - -;uint32_t get_timer(uint32_t base) -;{ -; uint32_t ret; -; ATOMIC_BLOCK(ATOMIC_FORCEON) -; { -; ret = timestamp; -; } -; return ret - base; -;} - - dseg ; called from banked only -gstimer: - push de - ex de,hl - ld hl,(uptime) - or a - sbc hl,de - pop de - ret - -;---------------------------------------------------------------------- - -gtimer: - push bc - ld b,h - ld c,l - or a - di - ld hl,(uptime) - sbc hl,bc - push hl - ei - ld hl,(uptime+2) - sbc hl,de - ex de,hl - pop hl - pop bc - ret - -;---------------------------------------------------------------------- -; intit timer interrupt - - dseg - -prt0ini: - in0 a,(tcr) - push af - and ~(M_TIE0+M_TDE0) ;stop timer 0 - out0 (tcr),a - - ld a,i - ld h,a - in0 a,(il) - and 0E0h - or IV$PRT0 - ld l,a - ld de,isvprt0 - ld (hl),e - inc hl - ld (hl),d - - ld hl,(f_cpu) - ld de,(f_cpu+2) - ld bc,PRT_PRE * 800 ;1/800 s == 1,25 ms interrupt rate - call div32_16 - - out0 (tmdr0l),l - out0 (tmdr0h),h - out0 (rldr0l),l - out0 (rldr0h),h - pop af - or (M_TIE0+M_TDE0) - out0 (tcr),a - ret - - -;---------------------------------------------------------------------- -; timer interrupt -; -; 1,25 ms clock tick - - - cseg ;common! -isvprt0: - push af - in0 a,(tcr) ;reset TIF0 flag - in0 a,(tmdr0l) - in0 a,(tmdr0h) - - push hl ;11 - ld hl,uptime ; 9 - inc (hl) ;10 - jr nz,iprt_1 ;6/8 38 - inc hl ; 4 - inc (hl) ;10 - jr nz,iprt_1 ;6/8 58 - inc hl ; 4 - inc (hl) ;10 - jr nz,iprt_1 ;6/8 - inc hl ; 4 - inc (hl) ;10 -iprt_1: - pop hl ; 9 - ld a,(time_to) - sub a,1 - jr c,iprt_0 - ld (time_to),a -iprt_0: - pop af - ei - ret - -uptime: - dw 0,0 -time_to: - db 0 - - end + title 'Time module for the Modular CP/M 3 BIOS' + + public ?time, gs_rtc + public prt0ini + public gtimer,gstimer + + extrn @date,@hour,@min,@sec + extrn f_cpu + extrn ioiniml,div32_16 + extrn msg.sm,msg.recv + extrn _b0call + + include config.inc + include z180reg.inc + + +;---------------------------------------------------------------------- +; c == 00h: get time +; c == ffh: set time + + cseg ; time must be done from resident memory +?time: + inc c ;zero if ff + ld c,3 + jr z,time_set + + ld a,(time_to) + or a + ret nz + + dec c +time_set: + b0call gs_rtc + ld a,0ffh + ld (time_to),a + ret + +;---------------------------------------------------------------------- +; c = 2: get time +; c = 3: set time + + dseg +gs_rtc: + + push hl + push de + + ld hl,(@date) + ld a,(@hour) + ld d,a + ld a,(@min) + ld e,a + ld a,(@sec) + ld b,a ;b = sec, c = subcommand + push hl ;2 + push de ;4 + push bc ;6 + ld hl,3 * 256 + 0 ;h = command, l = 0 + push hl ;8 + + ld h,l ;hl = 0 + add hl,sp + push hl + inc hl ;7 + + ld b,7 + call msg.sm + + pop hl ;8 + ld b,8 ; max receive message len + call msg.recv + + pop hl ;len/command (discard) + pop bc ;subc/sec + pop de + pop hl + ld a,b + ld (@sec),a + ld a,e + ld (@min),a + ld a,d + ld (@hour),a + ld (@date),hl + + pop de + pop hl + ret + +;---------------------------------------------------------------------- + +;uint32_t get_timer(uint32_t base) +;{ +; uint32_t ret; +; ATOMIC_BLOCK(ATOMIC_FORCEON) +; { +; ret = timestamp; +; } +; return ret - base; +;} + + dseg ; called from banked only +gstimer: + push de + ex de,hl + ld hl,(uptime) + or a + sbc hl,de + pop de + ret + +;---------------------------------------------------------------------- + +gtimer: + push bc + ld b,h + ld c,l + or a + di + ld hl,(uptime) + sbc hl,bc + push hl + ei + ld hl,(uptime+2) + sbc hl,de + ex de,hl + pop hl + pop bc + ret + +;---------------------------------------------------------------------- +; intit timer interrupt + + dseg + +prt0ini: + in0 a,(tcr) + push af + and ~(M_TIE0+M_TDE0) ;stop timer 0 + out0 (tcr),a + + ld a,i + ld h,a + in0 a,(il) + and 0E0h + or IV$PRT0 + ld l,a + ld de,isvprt0 + ld (hl),e + inc hl + ld (hl),d + + ld hl,(f_cpu) + ld de,(f_cpu+2) + ld bc,PRT_PRE * 800 ;1/800 s == 1,25 ms interrupt rate + call div32_16 + + out0 (tmdr0l),l + out0 (tmdr0h),h + out0 (rldr0l),l + out0 (rldr0h),h + pop af + or (M_TIE0+M_TDE0) + out0 (tcr),a + ret + + +;---------------------------------------------------------------------- +; timer interrupt +; +; 1,25 ms clock tick + + + cseg ;common! +isvprt0: ; + push af ; 11 + in0 a,(tcr) ;reset TIF0 flag 12 + in0 a,(tmdr0l) ; 12 + in0 a,(tmdr0h) ; 12 + ; + + push hl ;11 + ld hl,uptime ; 9 + inc (hl) ; 10 77 + jr nz,iprt_1 ; 6/8 -2 + inc hl ; 4 + inc (hl) ; 10 14 + jr nz,iprt_1 ; 6/8 + inc hl ; 4 + inc (hl) ;10 + jr nz,iprt_1 ;6/8 + inc hl ; 4 + inc (hl) ;10 +iprt_1: ; 85 138 + pop hl ; 9 + ld a,(time_to) ; 12 + sub a,1 ; 6 112 + jr c,iprt_0 ; 6/8 + ld (time_to),a ; 13 +iprt_0: ; 120 178 + pop af ; 9 + ei ; 3 + ret ; 9 141 199 + ; +intack 18 159 217 + +uptime: + dw 0,0 +time_to: + db 0 + + end -- 2.39.2