; ZMP-EP05.Z80 - Epson QX-10 overlay file for ZMP - 11-21-88 ; ; Adapted by Larry Davis - Glendale Litera QBBS - 818/956-6164 ; ; This file adapts ZMP version 1.5 to Epson QX-10 computers. ; ; Z80 SIO and 8253 baudrate generator ; ; System-dependent installation overlay for ZMP ; Author: Ron Murray ; ; 89/04/12 - Modified to ZMP v1.5 - George Conover ; Modified to v1.4 standard ; Modified to v1.3 standard rjm 12/10/88 ; ; 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 ; ;User-set variables: dport equ 11h ; data port sport equ dport+2 ; status port ; ;The following are used in setting up the Z80 SIO. ; rstins equ 18h ; Reset SIO - register 0 ; 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 0e8h ; 8 Tx bits, Tx enable, no RTS, DTR ; ; Baud rate ; baud1 equ 06h ;8253 baudrate generator port baud2 equ baud1+1 ; Timer port ; clkspd equ 4 ; Processor clock speed in MHz mspeed equ 003ch ; Current baud rate: as used by BYE etc overdrive equ 'A' ; Drive to find overlay files on overuser equ 0 ; User area to find files ; 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 .z80 ; use z80 code aseg ; absolute 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 ; Set port (0 or 1) ; 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: 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 ; to get the character in A in a,(dport) ; Get the character from the serial port ld l,a ; put in HL ld a,(parity) ; Strip hi bit if parity odd or even cp 'N' ; No parity? jr z,skippar ; yes, skip ld a,l and 07fh ; Strip parity bit ld l,a ; Put the character in HL skippar: ld a,l ; put the character back in A ; <== End of your own code 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 out (dport),a ; Put the character to the serial port ; <== End of your own code ret ; done ;Test for output ready: return TRUE (1) in HL if ok mordy: ; <== Insert your own code here in a,(sport) ; Read status port ld hl,0 ; assume not ready and 4 ; Look at bit 0 jr z,mordy1 inc hl ; otherwise set it 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 in a,(sport) ; Read status of serial port ld hl,0 ; assume not ready and 1 ; Test bit 1 jr z,mirdy1 inc hl ; otherwise set it mirdy1: ; <== 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 ; ; This routine sets a 300 ms break tone ; ld a,5 out (sport),a ; Output to the status port ld a,0f8h ; DTR normal, send break tone ; out (sport),a ; Output to the status port ; <== End of your own code ld hl,300 call waithlms ; wait 300 mS ; <== Insert your own code here ; to restore ld a,5 out (sport),a ; Output to the status port ld a,0e8h ; Restore normal, 8 bits, DTR on, etc. out (sport),a ; Output to the status port ; <== 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 ; Currently not implemented ; <== End of your own code ld a,l ; set/clear Z or a ret ;Turn DTR (and optionally RTS) ON. dtron: ; <== Insert your own code here ld A,5 ; Select register 5 out (sport),a ld A,REG5INS+2 ; 8 Tx bits, Tx enable, RTS, DTR out (sport),a ; <== End of your own code ret ;Turn DTR ( and RTS?) OFF dtroff: ; <== Insert your own code here ld A,5 ; Select register 5 out (sport),a ld a,reg5ins ; 8 Tx bits, Tx enable, no RTS, DTR out (sport),a ; <== End of your own code ret ;Initialise the UART init: ld hl,2 ; get parameters add hl,sp ex de,hl call getparm ; in HL ld (brate),hl call getparm ld (parity),hl ; parity call getparm ld (data),hl ; data bits call getparm ld (stop),hl ; stop bits ; <== Insert your own code here ; using values below ld A,0 ; Select register 0 out (sport),a ld a,rstins ; Reset SIO - 18h out (sport),a ; ld A,4 ; Select register 4 out (sport),a ld a,(parity) ; do parity ld e,003h ; assume even 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 ; ld a,3 ; Select register 3 out (sport),a ; 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 ld a,(data) ; set data bits cp 7 ; but 7 if required ld a,reg5ins ; 8 Tx bits, Tx enable, no RTS, DTR jr nz,setbs and 0bfh setbs: out (sport),a ; Set tx bits ; ld a,1 ; Select register 1 out (sport),a ld a,reg1ins ; No interrupts out (sport),a ; push ix ld de,(brate) ; set baud rate: get index ld ix,brval add ix,de add ix,de ld a,(ix) or (ix+1) jr z,setbrx ld a,0b6h out (baud2),a ld a,(ix) out (baud1),a ld a,(ix+1) out (baud1),a ld a,(brate) ; tell zmp it's ok ld (mspeed),a setbrx: pop ix ; <== End of your own code ret ; ;Baud rate factors, output to bauda to select baud rate ; brval: dw 0 ; 110 baud rate 0 dw 416 ; 300 baud rate 1 dw 0 ; 450 2 dw 0 ; 600 3 dw 0 ; 710 4 dw 104 ; 1200 baud rate 5 dw 52 ; 2400 baud rate 6 dw 26 ; 4800 baud rate 7 dw 13 ; 9600 baud rate 8 dw 0 ; 19200 9 dw 0 ; 38400 10 dw 0 ; 11 ; brate: dw 6 ; baud rate: parity: dw 'N' data: dw 8 ; data bits (will be 7 or 8) stop: dw 1 ; stop bits (will be 1 or 2) ; ; Set the port. ZMP supplies either 0 or 1 as a parameter. ; 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 ;**************************************************************************** ;Video terminal sequences: these are for ADM-3A: Modify as you wish ; Highlighting/Reverse video not enabled for QX-10 since it differs from ; CP/M to TPM. ; ;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: RET call print db esc,')',0 ret ;Inverse video off: invoff: RET call print db esc,'(',0 ret ;Turn off cursor: hide: RET call print db esc,'z',0 ret ;Turn on cursor: show: RET call print db esc,'v',0 ret ;Save cursor position: savecu: ret ;Restore cursor position: rescu: 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 ; 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 ; getvars: ld hl,uservars ret ; uservars: dw overdrive dw uservars ; if ($ - codebgn) gt ovsize toobig: jp errval ; Overlay too large! endif end