home *** CD-ROM | disk | FTP | other *** search
- ;
- ; Overlay to ZMP (Z-Modem Program), for the Kaypro CP/M computers.
- ; (Z80 SIO and 8116 baudrate generator.)
- ;
- ; Name: zmo-kp07.z80
- ;
- ; Dated: 10 April 1989
- ;
- ; Written by -
- ; Ron Murray, c/o Z-Node 62, 061-9-450-0200, Perth, Western Australia.
-
- ; kp07 - April 89. Updated "my" 06 (which had been a simple change of
- ; video code from Duerr's 05) to run on ZMP version 1.5.
- ; This version does not implement the dual port option. If
- ; any Kaypro owner has use of this option (it would have to
- ; take over the serial printer port), drop me a "line."
- ; In addition, the equate for RTS/CTS has been set at 'false'
- ; for the COM file included with this file. Tests have suggested
- ; that the Kaypro 2X/4/10/1 series' problems with dropping char-
- ; acters in terminal mode have to do with the inability of the
- ; Z80 to perform both its video and CPU functions in those machines
- ; at baud rates above 1200. The character dropping does not
- ; affect the quality of non-ASCII file transfers.
- ; Michael Broschat, GEnie address: M.BROSCHAT; also,
- ; Adam's RiBBS: Seattle WA area (206) 882-3684
-
- ; KP05 - Nov. 24, 88. Updated for ZMP version 1.4 (overlay drive/user
- ; equates). Added conditional to check RTS/CTS signals.
- ; Bill Duerr, GEnie ID: B.DUERR
- ; DKUG RBBS [313] 772-0522
- ;
- ; KP04 - Oct. 22, 88. Updated to allow program to be reentered properly,
- ; for 8-N-1 only -- still problems with even/odd parity.
- ; Bill Duerr, GEnie ID: B.DUERR
- ; DKUG RBBS [313] 772-0522
- ;
- ; KP03 - Oct. 12, 88 Modified to ZMP v1.3 standard rjm
- ;
- ;
- ; Insert your own code as necessary in this file. Code contained herein
- ; has been written in Z80 code for use with M80. Once assembled,
- ; convert to hex with RELHEX 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 clkspd variable.
- ;
- ; 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
- ;
- ;
- false equ 0
- true equ not false
- ;
- ; If the following equate is set to true, code will be added to set
- ; the RTS modem signal, telling the modem not to send any characters
- ; till RTS is reset, and also to check CTS if characters may be sent.
- ; This allows the Kaypro screen to keep up with the characters sent
- ; over the modem lines at higher speeds. (The modem must be able to
- ; recognize RTS and set CTS for this to work.)
- ;
- rtscts equ false
- ;
- ;Set the following two equates to the drive and user area which will contain
- ; ZMP's .OVR files, .CFG file, .FON file and .HLP file. Set both to zero
- ; (null) to locate them on the drive from which ZMP was invoked.
-
- overdrive equ 'A' ; Drive to find overlay files on ('A'-'P')
- overuser equ 0 ; User area to find files
-
- ;------------------------------------------------------------------------------
-
- ;User-set variables:
- clkspd equ 4 ; Processor clock speed in MHz
- mspeed equ 003ch ; Current baud rate: as used by BYE etc
- ; This MUST be the same as Mspeed in
- ; ZMP.H
-
-
- dport equ 04h ; Kaypro SIO data port
- sport equ dport+2 ; Modem control port
- mdrcv equ 01h ; Modem receive ready
- mdsnd equ 04h ; Modem send ready bit
- mdtxe equ 01h ; Modem send buffer empty, holding buffer empty
- rsterr equ 30h ; Reset parity and overrun flags - register 0
- reg1ins equ 0 ; No interrupts - register 1
- reg3ins equ 0c1h ; 8 Rx bits, Rx enable
- reg4ins equ 44h ; 16X baud rate, 1 stop bit, no parity
- reg5ins equ 0eah ; 8 Tx bits, Tx enable, RTS, DTR
-
- bauda equ 00h ; 8116 port for baudrate
- rstsio equ 18h ; Reset the SIO
- dcd equ 08h ; Data Carrier Detect
- dtr equ 80h ; Data Terminal Ready
- rts equ 02h ; Request to send
- cts equ 20h ; Clear to send
- brk equ 10h ; SIO Break
- sioerr equ 70h ; SIO error
-
- userdef equ 00145h ; 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
-
- org userdef
-
- esc equ 1bh
- ctrlq equ 11h
- cr equ 0dh
- lf equ 0ah
- bdos equ 5
-
- ;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 ; inverse video on
- jp invoff ; 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 on
- jp dtroff ; turn DTR 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
- jp getvars ; get system variables
- jp setport ; choose one of two (not implemented)
-
- ; Spare jumps for compatibility with future versions
-
- jp spare ; spare for later use
- jp spare ; spare for later use
- jp spare ; spare for later use
- jp spare ; spare for later use
- jp spare ; spare for later use
-
- ; Main code starts here
- ;
- codebgn equ $
- ;
- ;Screen print function
- scrnpr:
- ; <== Insert your own code here
- call print
- db 'This function not supported.',cr,lf,0
- ; <== End of your own code
- spare:
- ret
-
- ; User-defined entry routine
- userin:
- ret
- ; User-defined exit routine
- userout: ; Leave RTS off
- if rtscts
- ld a,05h ; Select register 5
- out (sport),a ; Send to the status port
- ld a,(reg5) ; Get register 5 settings
- and 255-rts ; Turn off RTS
- out (sport),a ; Send to the status port
- endif ; rtscts
- ret
-
- ;Get a character from the modem: return in HL
- ; It is not necessary to test for status
- mchin:
- ;-- Code added specific to Kaypro
- in a,(dport) ; get the character in A
- ;
- ; This routine checks parity, and if parity is not "none", strips high bit.
- ; This is needed, even if the filter is turned on, because CONNECT message
- ; is not filtered.
- ;
- ld l,a ; Save in L
- ld a,(parity) ; Check parity
- cp 'N' ; No parity?
- ld a,l ; Get the character back
- jr z,mchin1 ; Bypass following kludge
- and 7fh
- ld l,a ; put in HL
- mchin1:
- if rtscts
- ld a,05h ; Select register 5
- out (sport),a ; Send to the status port
- ld a,(reg5) ; Get register 5 settings
- and 255-rts ; Turn off RTS
- out (sport),a ; Send to the status port
- endif ; rtscts
- ;-- End of this block of machine specific code
- ld a,l ; get character from HL
- ld h,0
- or a ; set/clear Z
- ret
-
- ;Send a character to the modem
- mchout:
- ld hl,2 ; Get the character
- add hl,sp
- ld a,(hl) ; in A
- ;-- Code added specific to Kaypro
- out (dport),a ; Put the character to the serial port
- ;-- End of this block of machine specific code
- ret ; done
-
- ;Test for output ready: return TRUE (1) in HL if ok
- mordy:
- ;-- Code added specific to Kaypro
- ld hl,0 ; Assume not ready
- ;
- if rtscts
- ld a,10h ; Reset register 0
- out (sport),a ; Send to the status port
- in a,(sport) ; read status port
- and cts ; Is clear to send up
- jr z,mordy1 ; Branch if not clear to send
- endif ; rtscts
- ;
- ld a,10h ; Reset register 0
- out (sport),a ; Send to the status port
- in a,(sport) ; Read status port
- and mdsnd ; Isolate transmit empty bit
- jr z,mordy1 ; Branch if not ready
- inc hl ; otherwise set HL to indicate ready
- mordy1:
- ;-- End of this block of machine specific code
- ld a,l
- or a ; set/clear Z
- ret
-
- ;Test for character at modem: return TRUE (1) in HL if so
- mirdy:
- ;-- Code added specific to Kaypro
- ld a,05h ; Select register 5
- out (sport),a ; Send to the status port
- ld a,(reg5) ; Get register 5 settings
- or rts ; Turn on RTS
- out (sport),a ; Send to the status port
- ld hl,0 ; Assume not ready
- ld a,10h ; Reset register 0
- out (sport),a ; Send to the status port
- in a,(sport) ; Get the status
- and mdrcv ; Isolate receive ready bit
- jr z,mirdy1 ; Branch if not ready
- inc hl ; otherwise set HL to indicate ready
- mirdy1:
- ;-- End of this block of machine specific code
- ld a,l
- or a ; set/clear Z
- ret
-
- ;Send a break to the modem: leave empty if your system can't do it
- sndbrk:
- ;-- Code added specific to Kaypro
- ld a,5 ; Select register 5
- out (sport),a ; Send to the status port
- ld a,(reg5) ; Get parameters for register 5
- or brk ; Set the break tone
- out (sport),a ; Send to the status port
- ;-- End of this block of machine specific code
- ld hl,300
- call waitms ; wait 300 mS
- ;-- Code added specific to Kaypro
- ld a,5 ; Select register 5
- out (sport),a ; Send to the status port
- ld a,(reg5) ; Restore register 5 settings
- out (sport),a ; Send to the status port
- ;-- End of this block of machine specific code
- ret
-
- ;Test UART flags for error: return TRUE (1) in HL if error
- mdmerr:
- ;-- Code added specific to Kaypro
- ld hl,0 ; Assume no error
- ld a,011h ; Select read register 1
- out (sport),a ; Send to the status port
- in a,(sport) ; Get error status
- and sioerr ; Mask all but error bits
- ret z ; Return zeor in HL if no error
- inc hl ; Otherwise set HL to indicate error
- ret ; Return
-
-
- ;Turn DTR (and optionally RTS) ON.
- dtron:
- ;-- Code added specific to Kaypro
- ld a,05h ; Select register 5
- out (sport),a ; Send to the status port
- ld a,(reg5) ; Get register 5 settings
- out (sport),a ; Send to the status port
- ;-- End of this block of machine specific code
- ret
-
- ;Turn DTR ( and RTS?) OFF
- dtroff:
- ;-- Code added specific to Kaypro
- ld a,05h ; Select register 5
- out (sport),a ; Send to the status port
- ld a,(reg5) ; Get register 5 settings
- and 255-dtr ; Turn off DTR
- out (sport),a ; Send to the status port
- ;-- End of this block of machine specific code
- ret
-
- ;Initialise the UART
- init:
- ld hl,2 ; get parameters
- add hl,sp
- ld a,(hl) ; get lo
- ld (mspeed),a ; save in baud rate low memory
- inc hl
- inc hl ; bump for next
- ld a,(hl) ; get lo
- and 5Fh ; Convert to upper case
- ld (parity),a ; parity
- inc hl
- inc hl ; bump for next
- ld a,(hl) ; get lo
- and 0fh ; Make sure binary
- ld (data),a ; Save data bits
- cp 7 ; but 7 if required
- ld a,reg5ins ; 8 Tx bits, Tx enable, RTS, DTR
- jr nz,setbs
- ld a,reg5ins-040h ; Turn bit off
- setbs:
- ld (reg5),a
- inc hl
- inc hl ; bump for next
- ld a,(hl) ; get lo
- and 0fh ; Make sure binary
- ld (stop),a ; stop bits
- ; <== Insert your own code here
- ;-- Code added specific to Kaypro
- ld a,10h ; Reset register 0
- out (sport),a ; Send to the status port
- in a,(sport) ; read status port
- and DCD ; Is carrier up
- jr nz,initr ; Branch if carrier already there
- ld A,0 ; Select register 0
- out (sport),a ; Send to status port
- ld a,rstsio ; Reset SIO - 18h
- out (sport),a ; Send to status port
- ;
- ld A,4 ; Select register 4
- out (sport),a ; Send to status port
- ld a,(parity) ; do parity
- ld e,003h ; assume even parity
- cp 'E' ; even?
- jr z,setstop ; yes
- ld e,001h ; try odd
- cp 'O'
- jr z,setstop
- ld e,0 ; Indicate no parity
- setstop:
- ld a,(stop) ; set stop bits
- cp 2
- ld a,reg4ins ; 16X baud rate, 1 stop bit, no parity
- jr nz,onestop
- or 00ch ; set bits 2 and 3
- onestop:
- or e ; put parity bits in the register
- ;
- out (sport),a ; Send to status port
- ;
- ld a,3 ; Select register 3
- out (sport),a ; Send to status port
- ;
- ld a,(data) ; get data bits parameter field
- cp 7 ; is 7 required
- ld a,reg3ins ; 8 Rx bits, Rx enable
- jr nz,setbr
- and 07fh
- setbr:
- out (sport),a ; Set Rx bits
- ld a,5 ; Select register 5
- out (sport),a ; Send to status port
- ld a,(reg5) ; Get register 5 settings
- out (sport),a ; Set tx bits
- ;
- ld a,1 ; Select register 1
- out (sport),a
- ld a,reg1ins ; No interrupts
- out (sport),a ; Send to status port
- ;
- ld a,(mspeed) ; set baud rate: get index
- ld hl,brval
- ld e,a ; rate to DE
- ld d,0
- add hl,de
- ld a,(hl) ; get baud rate value
- out (bauda),a
- ; <== End of your own code
- initr: ret
-
- ;
- ; Baud rate factors, output to bauda to select baud rate
- ;
- bd10 equ 02h ; 110 baud rate 0
- bd30 equ 05h ; 300 baud rate 1
- bd12 equ 07h ; 1200 baud rate 5
- bd24 equ 0ah ; 2400 baud rate 6
- bd48 equ 0ch ; 4800 baud rate 7
- bd96 equ 0eh ; 9600 baud rate 8
- bd19k equ 0fh ; 19.2k baud rate 9
-
-
- ;Values for control reg for each baud rate: 0 if invalid
- brval:
- ; 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
- db 00,01,00,00,00,07,10,12,14,15
-
- ; <== End of your own code
- ret
-
- brate: db 6,0 ; baud rate:
- ; 0 = 110 baud 1 = 300 baud 2 = 450 baud
- ; 3 = 600 baud 4 = 710 baud 5 = 1200 baud
- ; 6 = 2400 baud 7 = 4800 baud 8 = 9600 baud
- ; 9 = 19200 baud
- parity: db 'N',0 ; parity (will be 'N', 'E' or 'O')
- data: db 8,0 ; data bits (will be 7 or 8)
- stop: db 1,0 ; stop bits (will be 1 or 2)
- reg5: db reg5ins
-
- ;****************************************************************************
- ;Video terminal sequences: these are for ADM-3A: 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) ; sane 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
-
- ;Inverse video on:
- invon:
- call print
- db esc,'B','0',esc,'B','1',0
- ret
-
- ;Inverse video off:
- invoff:
- call print
- db esc,'C','0',esc,'C','1',0
- ret
-
- ;Turn off cursor:
- hide:
- call print
- db esc,'C','4',0
- ret
-
- ;Turn on cursor:
- show:
- call print
- db esc,'B','4',0
- ret
-
- ;Save cursor position:
- savecu:
- call print
- defb esc,'B','6',0
- ret
-
- ;Restore cursor position:
- rescu:
- call print
- defb esc,'C','6',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 ; character at modem?
- jr nz,mrd2 ; yes, exit
- ld hl,1 ; else wait 1ms
- call waitms
- 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 ; Save the character to E for BDOS routine
- ld c,2 ; BDOS conout routine
- 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
- waits:
- push bc ; save bc
- push de ; de
- push ix ; and ix
- ld ix,0 ; then point ix to 0
- ; so we don't upset memory-mapped i/o
-
- ;Calculate values for loop constants. Need to have two loops to avoid
- ; 16-bit overflow with clock speeds above 9 MHz.
-
- outerval equ (clkspd / 10) + 1
- innerval equ (6667 / outerval) * clkspd
-
- 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 inner loop
- djnz wait11 ; decrement outer loop
- dec hl ; ok, decrement count in hl
- ld a,h
- or l
- jr nz,wait10
- pop ix ; done -- restore ix
- pop de ; de
- pop bc ; and 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
- waitms:
- 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
-
- ;Get address of user-defined variables
-
- getvars:
- ld hl,uservars
- ret
-
- uservars:
- dw overdrive ; .OVR etc. drive/user
- dw overuser
- setport:
- ret
-
- if ($ - codebgn) gt ovsize
- toobig: jp errval ; Overlay too large!
- endif
-
- end