home *** CD-ROM | disk | FTP | other *** search
- ;-----------------------------------------------------------------------------
- ;
- ; Heath-89 Overlay for ZMP15 (Z-Modem Program)
- ; modifications by Howard Dutton
- ;
- ;
- ; BE SURE TO CHANGE THE USER SET VARS: clkspd + overdrive + overuser
- ; ******************************************************************
- ;
- ; Name ZMOH89.Z80
- ;
- ; Dated Sep 14, 1988
- ;
- ; Written by -
- ; Ron Murray, c/o Z-Node 62, 061-9-450-0200, Perth, Western Australia.
- ;
- ; Modified to ZMP v1.2 standard rjm 15/9/88
- ; Modified to ZMP v1.3 standard rjm 11/10/88
- ; Modified to ZMP v1.4 standard rjm 20/11/88
- ;
- ;
- ;-----------------------------------------------------------------------------
- ;
- ;
- ; System-dependent code overlay for ZMODEM
- ;
- ;
- ;
- ; Insert your own code as necessary in this file. Code contained herein
- ; has been written in Z80 code for use with M80 or SLR. Assemble as follows:
- ;
- ; SLR ZMO-xx01/h
- ; MLOAD ZMP.COM=ZMODEM.COM,ZMO-xx01.HEX
- ; or
- ; M80 =ZMO-xx01.Z80
- ; RELHEX ZMO-xx01
- ; MLOAD ZMP.COM=ZMODEM.COM,ZMO-xx01.HEX
- ;
- ;
- ; (Don't use L80 without changing the source for assembly as a
- ; cseg file.)
- ;
- ;-----------------------------------------------------------------------------
- ;
- ;
- ; 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 contact me for another version. 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
-
- ;------------------------------------------------------------------------------
-
- ; User-set variables:
-
- clkspd equ 6 ; Processor clock speed in MHz
- debug equ false ; to allow debugging of overlay with Z8E etc.
-
- ;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
-
- ;------------------------------------------------------------------------------
-
-
- ; NOT user-set variables
-
- userdef equ 0145h ; origin of this overlay
- ; This address should not change with
- ; subsequent revisions.
- mspeed equ 03ch ; location of current baud rate.
- ovsize equ 0400h ; max size of this overlay
-
- .z80 ; use z80 code
- aseg ; absolute
-
- if debug
- org 100h ; so you can debug it with cebug, zsid, etc
- else
- org userdef
- endif
-
-
- mport equ 0d8h ; the modem port on a h88-3 serial card
- conport equ 0e0h ; the console serial port on a H89
-
- esc equ 1bh
- ctrlq equ 11h
- cr equ 0dh
- lf equ 0ah
- bdos equ 5
-
-
- codebgn equ $
-
- ;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 ; set port #0 or #1
-
- ; 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
- ;
- ;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: leave empty if not needed
- userin:
- ret
-
- ; User-defined exit routine: leave empty if not needed
- userout:
- ret
-
-
- ;Get a character from the modem: return in HL
- mchin:
- push bc
- in a,(mport)
- 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)
- out (mport),a
- ret ; done
-
- ;Test for output ready: return TRUE (1) in HL if ok
- mordy:
- ld hl,0 ;
- in a,(mport+5) ;
- bit 5,a ; bit 5 is set if uart is ready for a char
- jp z,mordy1 ;
- ld hl,1
-
- mordy1: ld a,l ; set/clear Z
- or a
- ret
-
- ;Test for character at modem: return TRUE (1) in HL if so
- mirdy:
- ld hl,0 ;
- in a,(mport+5) ;
- bit 0,a ; bit 0 is set if data is ready
- jp z,mirdy1 ;
- ld hl,1
-
- mirdy1: 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:
-
- in a,(mport+3) ;
- set 6,a ; set break bit
- out (mport+3),a ;
-
- push af
- ld hl,300 ; wait 300 mS
- call waithlms
- pop af
-
- res 6,a ; reset break bit
- out (mport+3),a ;
-
- ret
- ;
- ;Test UART flags for error: return TRUE (1) in HL if error.
- mdmerr:
- ld hl,0
- in a,(mport+5) ; get line status
- and 00001110B ; mask
- jp z,mdmer1 ; a should = 0 if everything is ok
- ld hl,1 ;
-
- mdmer1: ld a,l ; set/clear Z
- or a
- ret
-
-
- ;Turn DTR ON
- dtron:
- in a,(mport+4) ;
- set 0,a ; set the DTR bit
- out (mport+4),a ;
-
- ret
-
-
-
- ;Turn DTR OFF
- dtroff:
- in a,(mport+4) ;
- res 0,a ; reset the DTR bit
- out (mport+4),a ;
-
- ret
-
-
- ;
- ; Set the port. ZMP supplies either 0 or 1 as a parameter. You're on your
- ; own here -- your system is bound to be different from any other! You may
- ; implement a software switch on all the modem-dependent routines, or perhaps
- ; you can have one or two centralised routines for accessing the UARTs and
- ; modify the code from this routine to select one or the other. (Who said
- ; there was anything wrong with self-modifying code?). If you have only one
- ; UART port, or if you don't want to go through all the hassles, just have
- ; this routine returning with no changes made. Note that ZMP calls this
- ; routine twice -- once for each port value -- on initialisation.
- ;
- setport:
- ld hl,2 ; get port number
- add hl,sp
- ex de,hl
- call getparm ; in HL (values are 0 and 1)
-
- ; <== Insert your own code here
-
- ; <== End of your own code
- ret
-
- port: ds 1
-
-
- ;Initialise the uart
-
- init: ld hl,2 ; get parameters
- add hl,sp
- ex de,hl
- call getparm ; in HL
- ld (brate),hl ; baud rate
- call getparm
- ld (parity),hl ; parity
- call getparm
- ld (data),hl ; data bits (BINARY 7 or 8)
- call getparm
- ld (stop),hl ; stop bits (BINARY 1 or 2)
-
- ; get the 8250 ready for programming
- ld a,0 ; clear interrupts
- out (mport+1),a ;
-
- ld a,00010000B ; set to loop-back mode
- out (mport+4),a ;
-
- ; program the baud-rate (if it's valid)
- ld hl,(brate) ; check to see if baud-rate is valid
- ld de,12 ;
- or a ; clear carry
- sbc hl,de ; hl=brate-12
- jp p,prb1 ; negitive if brate is 0..11
-
- ld a,l ;
- ld (mspeed),a ; let zmp know it's valid
-
- ld a,10000000B ; set divisor latch access bit
- out (mport+3),a ;
-
- ld hl,(brate) ; compute offset to baud-rate divisor
- add hl,hl ;
- ex de,hl ;
- ld hl,brtbl ;
- add hl,de ; HL now has address of divisor
- ld a,(hl) ; get the low-order byte
- out (mport),a ;
- inc hl ;
- ld a,(hl) ;
- out (mport+1),a ;
-
- ; program the: type of parity / # data bits / # stop bits
- prb1: ld b,0 ; set the LCR value (in B for now) to 0
- ld a,(parity) ; set bits in B to type of parity
- cp 'N' ;
- jp z,parN ;
- cp 'E' ;
- jp z,ParE ;
- cp 'O' ;
- jp z,ParO ;
- Skip3: ld a,(Data) ; set bits in B to # of data bits
- cp 7 ;
- jp z,data7 ;
- cp 8 ;
- jp z,data8 ;
- Skip4: ld a,(Stop) ;
- cp 1 ;
- jp z,Stop1 ;
- cp 2 ;
- jp z,Stop2 ;
- Skip5: ld a,b ; get 'LCR' value
- out (mport+3),a ; (also de-selects divisor access)
-
- ; take 8250 out of loop-back mode
- in a,(mport) ; read a char
- add hl,hl ; waste some time
- add hl,hl ;
- in a,(mport) ; read another char
- ld a,0 ;
- out (mport+4),a ; take 8250 out of loop-back mode
-
- ret
-
- ; Types of parity
- ParN:
- jp Skip3
- ParE:
- set 3,b
- set 4,b
- jp Skip3
- ParO:
- set 3,b
- jp Skip3
- ; Number of data bits
- Data7:
- set 1,b
- jp Skip4
- Data8:
- set 0,b
- set 1,b
- jp Skip4
- ; Number of stop bits
- Stop1:
- jp Skip5
- Stop2:
- set 2,b
- jp Skip5
-
- ; baud rate divisor table for 8250
- brtbl: dw 1047 ; 110 0
- dw 384 ; 300 1
- dw 256 ; 450 2
- dw 192 ; 600 3
- dw 162 ; 710 4
- dw 96 ; 1200 5
- dw 48 ; 2400 6
- dw 24 ; 4800 7
- dw 12 ; 9600 8
- dw 6 ; 19200 9
- dw 3 ; 38400 10
- dw 2 ; 57600 11
-
- ;--------------------------------------------------------------------------
-
- stop: dw 1 ; stop bits
- parity: dw 'N' ; parity
- data: dw 8 ; data bits
- brate: dw 5 ; baud rate: 1200
-
- ;--------------------------------------------------------------------------
- ;Values of brate for each baud rate
- ;
- ; baud rate brate
- ;
- ; 110 0
- ; 300 1
- ; 450 2
- ; 600 3
- ; 710 4
- ; 1200 5
- ; 2400 6
- ; 4800 7
- ; 9600 8
- ; 19200 9
- ; 38400 10
- ; 57600 11
- ;
-
- ;****************************************************************************
- ;Video terminal sequences: these are for the H19
- ;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
-
- ; using values in row and col
- call print
- db esc,'Y',0 ; H19 leadin
- ld a,(row) ; row first
- add a,' ' ; add offset
- call cout
- ld a,(col) ; sane for column
- add a,' '
- call cout
-
- ret
-
- row: ds 2 ; row
- col: ds 2 ; column
-
-
- ;Clear screen:
- cls:
- call print
- db esc,'E',0
- ret
-
- ;Inverse video on:
- invon:
- call print
- db esc,'p',0
- ret
-
- ;Inverse video off:
- invoff:
- call print
- db esc,'q',0
- ret
-
- ;Turn off cursor:
- hide:
- call print
- db esc,'x5',0
- ret
-
- ;Turn on cursor:
- show:
- call print
- db esc,'y5',0
- ret
-
- ;Save cursor position:
- savecu:
- call print
- db esc,'j',0
- ret
-
- ;Restore cursor position:
- rescu:
- call print
- db esc,'k',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 ********************************
- ; Do not change anything below here.
-
- ;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
- waiths:
- 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
- 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
-
- ;Get address of user-defined variables
-
- getvars:
- ld hl,uservars
- ret
-
- uservars:
- dw overdrive ; .OVR etc. drive/user
- dw overuser
-
-
- if ($ - codebgn) gt ovsize
- toobig: jp errval ; Overlay too large!
- endif
-
- end