; PROGRAM: ZMO-MIC5.Z80 ; AUTHOR: Ian Justman ; VERSION: 1.5 ; DATE: 14 Sept, 1988 ;----------------------------------------------------------------------- ; This overlay is set up for a Multitech MIC-500 computer ; Uses a Z80 DART and Z80 CTC baudrate generator ;----------------------------------------------------------------------- ; 89/04/12 - Modified to ZMP v1.5 - George Conover ; 89/03/15 - Removed the beginning remarks to make the file ; smaller. If you need the remarks there are in the ; file ZMP-BLNK.Z80 - George Conover ; 89/03/14 - Modified to ZMP v1.4 - George Conover ; 89/00914 - First version of this file - Ian Justman ; ; Written by - ; Ron Murray, c/o Z-Node 62, 061-9-450-0200, Perth, Western Australia. ;----------------------------------------------------------------------- NO EQU 0 YES EQU NOT NO ; ;------------------------------------------------------------------------------ ; User-set variables ; CLKSPD EQU 4 ; Processor clock speed in MHz ; ;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 ; DPORT EQU 88H ; DART data port SPORT EQU DPORT+2 ; DART status port ; ;The following are used in setting up the Z80 DART. ; RSTINS EQU 18H ; Reset DART - 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 ; BAUDA EQU 85H ; Baud rate generator for serial chan a ; ; NOT user-set variables ; USERDEF EQU 00145H ; Origin of this overlay: get this value ; ; From the .SYM file produced when ; ; ZMP.COM is linked MSPEED EQU 003CH ; Current baud rate: as used by BYE etc ; ; ZMP.H 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 ; CODEBGN EQU $ ; JUMPTAB: 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 ; ; Screen print function ; SCRNPR: DS 0 ; ; <== 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 YES (1) in HL if ok ; MORDY: DS 0 ; ; <== 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: DS 0 ; ; <== End of your own code ; LD A,L ; Set/clear Z OR A RET ; ; Test for character at modem: return YES (1) in HL if so ; MIRDY: DS 0 ; ; <== 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: DS 0 ; ; <== 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: DS 0 ; ; <== 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 milliseconds ; ; <== 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 YES (1) in HL if error ; MDMERR: DS 0 ; ; <== 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: DS 0 ; ; <== 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: DS 0 ; ; <== 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 DART - 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 LD A,47H OUT (BAUDA),A LD A,(BRATE) ; Set baud rate: get index LD HL,BRVAL LD C,A ; Rate to BC LD B,0 ADD HL,BC LD A,(HL) ; Get baud rate value OR A ; 0 = invalid JR Z,SETBRX OUT (BAUDA),A LD A,(BRATE) ; Tell zmp it's ok LD (MSPEED),A ; SETBRX: DS 0 ; ; <== End of your own code ; RET ; ; Baud rate factors, output to bauda to select baud rate ; BD10 EQU 00H ; 110 baud rate 0 BD30 EQU 80H ; 300 baud rate 1 BD12 EQU 20H ; 1200 baud rate 5 BD24 EQU 10H ; 2400 baud rate 6 BD48 EQU 08H ; 4800 baud rate 7 BD96 EQU 04H ; 9600 baud rate 8 BD19K EQU 02H ; 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,10,11,12 DB 00,128,00,00,00,32,16,08,04,02,00,00,00,00 BRATE: DS 2 ; 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 10 = 38400 baud 11 = 57600 baud ; 12 = 76800 baud 13 = 115200 baud ; PARITY: DS 2 ; Parity (will be 'N', 'E' or 'O') DATA: DS 2 ; Data bits (will be 7 or 8) STOP: DS 2 ; 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 ; ; 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 column ; 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,')',0 RET ; ; Inverse video off ; INVOFF: CALL PRINT DB ESC,'(',0 RET ; ; Turn off cursor ; HIDE: CALL PRINT DB ESC,'z',0 RET ; ; Turn on cursor ; SHOW: 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 -------------------------- ; 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 1 ms 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 registers 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 ; ; 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 low INC HL LD D,(HL) ; Then hihi 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 is too large ENDIF ; END