; ZMP180B3.Z80 -- SB180 computer overlay file for ZMP -- 10/15/88
;
; This file adapts ZMP13 to the SB180/FX computer; HD64180 ASCII port 0.
;
; Assemble with ZAS or SLR180
;
;
; vB.3 Added fixes outlined in ZMP-OVL.UPD for ZMP13 10/15/88 John Fort
;
; vB.2 Beta-test version 2 09/27/88 Bill Biersdorf
; -- added conditionals for clock speeds
; -- added equate 'dtrfx' for latch DTR on the 'FX
; -- character framing may work on non-FX, not sure
;
; vB.1 Beta-test version 1 09/24/88 Bill Biersdorf
; -- works with 9 MHz SB180-FX
; -- no provisions for stop bit, word length, or parity change
;
;
; System-dependent installation overlay for ZMP
; Author: Ron Murray
;
; Insert your own code as necessary in this file. Code contained herein
; has been written in HD64180 code for use with ZAS. Assemble with the h
; option to create a .HEX file, and use MLOAD to overlay it over the main
; ZMPX.COM file to produce your very own ZMP.COM.
;
; Notes on modifying this file:
; Hi-Tech C requires that functions do not change either index register
; (IX or IY). If your overlay requires either of these to be changed, ensure
; they are restored to their original values on return.
; Since collecting parameters from C functions can be tricky, only change
; the parts marked 'Insert your own code here'. Do NOT modify the jump
; table at the start. Do NOT modify the entry/exit sections of each
; function. Do NOT pass 'GO'. Do NOT collect $200.
; Apart from defining modem functions, this file also defines terminal
; characteristics. Most have been set up for ADM-3A (with a few of my own
; additions). Modify to suit your own terminal. An inline print routine
; is provided for printing strings in the usual way: usage is
;
; call print
; db 'required string',0
;
; Don't forget to set your clock speed at the Select-a-speed section.
; Set only one of cpu12, cpu9, or cpu6 to true. Set 'dtrfx' to true for
; your SB180-FX for proper DTR operation.
;
; If you find your overlay exceeds the maximum size (currently 0400h),
; you will have to re-compile the whole thing. Good luck. You might try
; informing us if you need to do this: if too many people need to do it, we
; haven't allowed enough room.
;
; Ron Murray 15/8/88
;
;Some fundamental truths
false equ 00h
true equ not false
;Select-a-speed ; NOTE: set only ONE of the following to true
iport equ 08h ; MODEM data in port
oport equ 06h ; MODEM data out port
cport equ 00h ; MODEM control port
mstat equ 04h ; MODEM status port
bport equ 02h ; MODEM baudrate port
mdrcv equ 80h ; receive ready bit
mdsnd equ 02h ; send ready bit
if cpu12
clkspd equ 12
endif
if cpu9
clkspd equ 9
endif
if cpu6
clkspd equ 6 ; Processor clock speed in MHz
endif
mspeed equ 003ch ; Current baud rate: as used by BYE etc
; This MUST be the same as Mspeed in
; ZMP.H
userdef equ 0145h ; origin of this overlay: get this value
; from the .SYM file produced when ZMP.COM
; is linked
ovsize equ 0400h ; max size of this overlay
;Jump table for the overlay: do NOT change this
jump_tab:
jp scrnpr ; screen print
jp mrd ; modem read with timeout
jp mchin ; get a character from modem
jp mchout ; send a character to the modem
jp mordy ; test for tx buffer empty
jp mirdy ; test for character received
jp sndbrk ; send break
jp cursadd ; cursor addressing
jp cls ; clear screen
jp invon ; highlight (inverse video) on
jp invoff ; highlight (inverse video) off
jp hide ; hide cursor
jp show ; show cursor
jp savecu ; save cursor position
jp rescu ; restore cursor position
jp mint ; service modem interrupt
jp invec ; initialise interrupt vectors
jp dinvec ; de-initialise interrupt vectors
jp mdmerr ; test uart flags for error
jp dtron ; turn DTR (and RTS) ON
jp dtroff ; turn DTR (and RTS) OFF
jp init ; initialise uart
jp wait ; wait seconds
jp mswait ; wait milliseconds
jp userin ; user-defined entry routine
jp userout ; user-defined exit routine
; Spare jumps for compatiblity with future versions.
jp spare ; spares for later use
jp spare ; spares for later use
jp spare ; spares for later use
jp spare ; spares for later use
jp spare ; spares for later use
;
; Main code starts here
;
codebgn equ $
;
;Screen print function
scrnpr:
; <== Insert your own code here
call print
db cr,lf
db 'Screen-print function not supported.',cr,lf,lf
db 0
; <== End of your own code
spare:
userin:
userout:
ret
;Get a character from the modem: return in HL
; It is not necessary to test for status
mchin:
push bc
; <== Insert your own code here
in0 a,(iport) ; to get the character in A
; <== End of your own code
ld l,a ; put in HL
ld h,0
or a ; set/clear Z
pop bc
ret
;Send a character to the modem
mchout:
ld hl,2 ; get the character
add hl,sp
ld a,(hl) ; in A
; <== Insert your own code here
out0 (oport),a
; <== End of your own code
ret ; done
;Test for output ready: return TRUE (1) in HL if ok
mordy:
; <== Insert your own code here
ld hl,00h ; assume not ready for now
in0 a,(mstat)
in0 a,(mstat) ; do twice for valid DCD
and mdsnd
jr z,mordy1 ; still not ready
inc hl ; ready, so set HL
mordy1: ; <== End of your own code
ld a,l ; set/clear Z
or a
ret
;Test for character at modem: return TRUE (1) in HL if so
mirdy:
; <== Insert your own code here
ld hl,00h ; assume not ready for now
in0 a,(mstat)
in0 a,(mstat) ; do twice for valid DCD
and mdrcv
jr z,mirdy1 ; still not ready
inc hl ; ready, so set HL
mirdy1: ; <== End of your own code
; <== End of your own code
ld a,l ; set/clear Z
or a
ret
;Send a break to the modem: leave empty if your system can't do it
sndbrk:
; <== Insert your own code here
; to go to 'break' level
; <== End of your own code
ld hl,300
call waithlms ; wait 300 mS
; <== Insert your own code here
; to restore
; <== End of your own code
ret
;Test UART flags for error: return TRUE (1) in HL if error
mdmerr:
; <== Insert your own code here
xor a ; not yet implemented
; <== End of your own code
ld a,l ; set/clear Z
or a
ret
;Turn DTR (and RTS) ON. (reset)
dtron:
; <== Insert your own code here
in0 a,(cport)
and 0efh ; RTS on
out0 (cport),a
if dtrfx
call dtrstat ; pull control latch
ld a,10111111b ; mask off DTR bit
and b ; and it out
ld b,a
ld a,0ffh ; set up for write
ld hl,(1) ; get address of BIOS
ld l,3fh ; add offset for control latch
ld de,dtrdone
push de ; save return vector
jp (hl) ; go to the latch routine
endif
if not dtrfx
ret
endif
; <== End of your own code
;Turn DTR (and RTS) OFF. (set)
dtroff:
; <== Insert your own code here
in0 a,(cport)
or 10h ; RTS off
out0 (cport),a
if dtrfx
call dtrstat ; pull control latch
ld a,01000000b ; mask off DTR bit
or b ; or it in
ld b,a
ld a,0ffh ; set up for write
ld hl,(1) ; get address of BIOS
ld l,3fh ; add offset for control latch
ld de,dtrdone
push de ; save return vector
jp (hl) ; go to the latch routine
endif
if not dtrfx
ret
endif
; <== End of your own code
dtrdone:
ret
;Needed to prevent changes to other control latch registers.
if dtrfx
dtrstat:
xor a
ld hl,(1) ; get address of BIOS
ld l,3fh ; add offset of control latch
jp (hl) ; go get status
endif
;Initialise the UART
init:
ld hl,2 ; get parameters
add hl,sp
ex de,hl
call getparm ; in HL
ld (brate),hl ; baud rate
ld a,l ; only 1 byte
ld (mspeed),a ; save for future use
call getparm
ld (parity),hl ; parity
call getparm
ld (data),hl ; data bits
call getparm
ld (stop),hl ; stop bits
initsio: ; using values below
in0 a,(cport)
and 0efh ; RTS on
or 68h ; enable xmit, receive; clear errors
out0 (cport),a
ret
setbaud:
ld a,(brate) ; get BRATE into A
ld e,a ; and DE
ld d,0
ld hl,divisors ; get offset into baudrate divisor table
add hl,de
ld a,(hl) ; fetch code
or a ; 00h means upsupported code
jr z,sbexit ; exit if bad
out0 (bport),a ; else set baud
ret
sbexit:
call print
db 'That rate not supported by this system.',cr,lf,0
ret
; Parity is controlled by bit 1 of CPORT and
; bit 4 of BPORT as follows:
;
; BPORT CPORT
; Parity Bit 4 Bit 1
; Off - 0
; Odd 1 1
; Even 0 1
;
setprty:
;; ld a,(parity) ; get parity into A
;; cp 'E'
;; jr z,prevn ; even
;; cp 'O'
;; jr z,prodd ; odd
;;
;; ; else assume none
;;proff: in0 a,(cport)
;; and 0fdh ; reset bit 1
;; push af ; save
;; in0 a,(bport)
;; jr prnxt
;;
;;prevn: in0 a,(cport)
;; or 02h ; set bit 1
;; push af ; save
;; in0 a,(bport)
;; and 0efh ; reset bit 4
;; jr prnxt
;;
;;prodd: in0 a,(cport)
;; or 02h ; set bit 1
;; push af ; save
;; in0 a,(bport)
;; or 10h ; set bit 4
;;
;;prnxt:
;; out0 (bport),a ; set for (even) or (odd)
;; pop af
;; out0 (cport),a ; set for (even/odd) or (none)
;; call initsio ; reset the UART
ret
; The number of stop bits is controlled by bit
; 0 of CPORT, as follows:
;
; Stop bits Bit 0
; 1 0
; 2 1
;
;;setstop:
;; ld a,(stop) ; get stopbits into A
;; cp 2
;; jr z,stop2 ; two
;;
;; ; assume one
;;stop1: in0 a,(cport)
;; and 0feh ; reset bit 0
;; jr ssnxt
;;
;;stop2: in0 a,(cport)
;; or 01h ; set bit 0
;;
;;ssnxt: out0 (cport),a
;; call initsio ; reset the UART
ret
; The number of bits per character is controlled by
; bit 2 of CPORT as follows:
;
; BPC Bit 2
; 7 0
; 8 1
;
;;wlength:
;; ld a,(data) ; get word length
;; cp 7
;; jr z,wlen7 ; 7
;;
;; ; assume 8
;;wlen8: in0 a,(cport)
;; or 04h ; set bit 2
;; jr wlnxt
;;
;;wlen7: in0 a,(cport)
;; and 0fbh ; reset bit 2
;;
;;wlnxt: out0 (cport),a
;; call initsio ; reset the UART
;****************************************************************************
; Video terminal sequences: these are for Televideo 950 -- Modify as you wish
;Cursor addressing:
cursadd:
ld hl,2 ; get parameters
add hl,sp
ex de,hl
call getparm ; in HL
ld (row),hl ; row
call getparm
ld (col),hl ; column
; <== Insert your own code here
; using values in row and col
call print
db esc,'=',0 ; ADM-3A leadin
ld a,(row) ; row first
add a,' ' ; add offset
call cout
ld a,(col) ; same for column
add a,' '
call cout
; <== end of your own code
ret
row: ds 2 ; row
col: ds 2 ; column
;Clear screen:
cls:
call print
db 01ah,0
ret
;Highlight on:
invon:
call print
db esc,')',0
ret
;Highlight off:
invoff:
call print
db esc,'(',0
ret
;Turn off cursor:
hide:
call print
db esc,'.0',0
ret
;Turn on cursor:
show:
call print
db esc,'.1',0
ret
;Service modem interrupt:
mint:
ret ; my system doesn't need this
;Initialise interrupt vectors:
invec:
ret ; ditto
;De-initialise interrupt vectors:
dinvec:
ret ; ditto
;****************** End of user-defined code ********************************
; Don't change anything below this point. We needed some assembly language
; stuff for speed, and this seemed like a good place to put it.
;Modem character test for 100 ms
mrd:
push bc ; save bc
ld bc,100 ; set limit
mrd1:
call mirdy ; char at modem?
jr nz,mrd2 ; yes, exit
ld hl,1 ; else wait 1ms
call waithlms
dec bc ; loop till done
ld a,b
or c
jr nz,mrd1
ld hl,0 ; none there, result=0
xor a
mrd2:
pop bc
ret
; Inline print routine: destroys A and HL
print:
ex (sp),hl ; get address of string
ploop:
ld a,(hl) ; get next
inc hl ; bump pointer
or a ; done if zero
jr z,pdone
call cout ; else print
jr ploop ; and loop
pdone:
ex (sp),hl ; restore return address
ret ; and quit
;
;Output a character in A to the console
;
cout:
push bc ; save regs
push de
push hl
ld e,a ; character to E
ld c,2
call bdos ; print it
pop hl
pop de
pop bc
ret
;Wait(seconds)
wait:
ld hl,2
add hl,sp
ex de,hl ; get delay size
call getparm
; fall thru to..
;Wait seconds in HL
waithls:
push bc ; save bc
push de ; de
push ix ; and ix
ld ix,0 ; then point ix to 0
wait10:
ld b,outerval
wait11:
ld de,innerval
wait12:
bit 0,(ix) ; time-wasters
bit 0,(ix)
bit 0,(ix) ; 20 T-states each
bit 0,(ix)
bit 0,(ix)
bit 0,(ix)
dec de
ld a,e
ld a,d
or e
jr nz,wait12 ; 150 T-states per loop
djnz wait11 ; decrement outer loop
dec hl
ld a,h
or l
jr nz,wait10
pop ix
pop de
pop bc
ret
;Wait milliseconds
mswait:
ld hl,2
add hl,sp
ex de,hl ; get delay size
call getparm
; fall thru to..
;Wait milliseconds in HL
waithlms:
push de
w1ms0:
ld de,39 * clkspd
w1ms1:
dec de
ld a,d
or e
jr nz,w1ms1
dec hl
ld a,h
or l
jr nz,w1ms0
pop de
ret
;Get next parameter from (de) into hl
getparm:
ex de,hl ; get address into hl
ld e,(hl) ; get lo
inc hl
ld d,(hl) ; then hi
inc hl ; bump for next
ex de,hl ; result in hl, address still in de
ret
if [$ - codebgn] gt ovsize
toobig: jp errval ; Overlay too large!
endif
end
lt in hl, address still in de
ret
if [$ - codebgn] gt ovsize
toobig: jp errval ; Overlay too large!
en