;----------------------------------------------------------------------------- ; ; Overlay for ZMP ffor HP12X ; ; Name zmo-hp.azm ; ; set up for compile with z80mr ; ; Written by - ; Ron Murray, c/o Z-Node 62, 061-9-450-0200, Perth, Western Australia. ; ; 89/04/12 - Modified to ZMP v1.5 - George Conover ; 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 ; Added HP code MWR 2/8/89 ; Attemp at correct cursor contrl 2/10/89 ; ;----------------------------------------------------------------------------- ; ; ; 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.) ; ;----------------------------------------------------------------------------- ; ; ; Notes on modifying this file: ; ; 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 the 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. Examples provided are 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 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 1 ;------------------------------------------------------------------------------ ; User-set variables: clkspd equ 4 ; 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 'B' ; 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 org userdef 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 jp spare ; spare for later use ; ; Main code starts here ; ;Screen print function scrnpr: ; <== Insert your own code here call print db 1bh,'0',0 ; <== End of your own code spare: ret ; User-defined entry routine: leave empty if not needed userin: ld bc,73ffh call bdos ; map reader and punch to port1 call print db 'Version for HP12X Series',cr,lf,0 call print db 1bh,'&i0s25d4M',1bh,'&i10s16d4M',cr,lf,0 ; try and set up vectors for 8 bits ld bc,7effh ld de,jbuf call bdos ld hl,(jump) ld (real),hl ld hl,ineight ld (jump),hl ld a,1 ld (flag),a ld bc,7effh ld de,jbuf call bdos ret ; more hp stuff for 8 bit setup ineight:call readin ld a,b ret ; end of more hp stuff for 8 bit setup ; User-defined exit routine: leave empty if not needed userout: ; begin hp exit call print db 1bh,'E',0 ; cold boot system ret ;Get a character from the modem: return in HL mchin: push bc ;start or HP125 code push de ld c,03h call bdos pop de ;end of HP 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) ;start of HP code push bc push de ld e,a ld c,04h call bdos pop de pop bc ;end of HP code ret ; done ;Test for output ready: return TRUE (1) in HL if ok mordy: ;start of HP code ld h,0 ld l,1 ;end of hp code ld a,l ; set/clear Z or a ret ;Test for character at modem: return TRUE (1) in HL if so mirdy: ;start of hp code push bc push de ld bc,70ffh call bdos ld h,0 ld l,a pop de pop bc ;end og HP 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 ld hl,300 ; wait 300 mS call waithm ; <== End of your own code ret ; ;Test UART flags for error: return TRUE (1) in HL if error. mdmerr: ; <== Insert your own code here ; <== End of your own code ld a,l ; set/clear Z or a ret ;Turn DTR ON dtron: ; <== Insert your own code here ; <== End of your own code ret ;Turn DTR OFF dtroff: ; <== Insert your own code here ; <== 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 ; 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) ; <== Insert your own code here ; using values below ld (mspeed),a ; don't forget to load mspeed with the ; current brate value if the new rate is ; valid. See table of values below. ; <== End of your own code ret ;-------------------------------------------------------------------------- stop: dw 1 ; stop bits parity: dw 'N' ; parity data: dw 8 ; data bits brate: dw 7 ; baud rate: ;-------------------------------------------------------------------------- ;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 ; 76800 12 ; ; ; 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: for the HP125 ;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 ;start hp sequence call print db esc,'&a',0 push bc push de push hl ld hl,(row) call conv ld a,(tens) call cout ld a,(digits) call cout ld a,'r' call cout ld hl,(col) call conv ld a,(tens) call cout ld a,(digits) call cout ld a,'C' call cout pop hl pop de pop bc ret ; <== end of your own code ;more hp code for cursor control conv: ld de,0000h ld bc,000ah loop16: sbc hl,bc jp m,done inc e jp loop16 done: add hl,bc ld a,l add a,48 ld (digits),a ld a,e add a,48 ld (tens),a ret digits: ds 1 tens: ds 1 ; end of hp added code for cursor control row: ds 2 ; row col: ds 2 ; column ;Clear screen: cls: call print db 1bh,'H',1bh,'J',0 ret ;Inverse video on: invon: call print db 1bh,'&dA',0 ret ;Inverse video off: invoff: call print db 1bh,'&d@',0 ret ;Turn off cursor: hide: ret ;Turn on cursor: show: 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 ******************************** ; 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 waithm 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 waithm: 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 ;add hp stuff readin: db 0c3h real: ds 2 jvn: db 7 flag: db 0 opcode: ds 1 jump: ds 2 jbuf: equ jvn ;end added hp stuff end