; PROGRAM: ZMO-CP05.Z80 ; AUTHOR: Bruce Dudley ; VERSION: 1.5 ; DATE: 19 Sept, 1988 ;----------------------------------------------------------------------- ; This overlay is set up for an Amstrad CPC6128 under CPM Plus, ; with a Zenith Z19/Z29 terminal emulation and a Z80SIO and 8253 ; counter. ;----------------------------------------------------------------------- ; 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 ; 88/10/12 - Modified to ZMP v1.3 - Ron Murray ; 88/09/15 - Modified to ZMP v1.2 - Ron Murray ; 88/08/28 - First version of this file - Bruce Dudley ; ; 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 ; DEBUG EQU NO ;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 ; ; may change with subsequent revisions MSPEED EQU 05CH ; 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 ; DEBUG ; ESC EQU 1BH CTRLQ EQU 11H CR EQU 0DH LF EQU 0AH BDOS EQU 5 ; ; Amstrad CPC6128 specific equates ; MDATA EQU 0FADCH ; Data port MSTAT EQU 0FADDH ; Status port RDA EQU 0 ; Received data available TBE EQU 2 ; Tx ready ONHOOK EQU 7FH ONLINE EQU 80H ERROR EQU 70H BREAK EQU 0F8H ; ; 8253 Counter equates ; CTCONT EQU 0FBDFH ; Control register of the 8253 CTC0 EQU 0FBDCH ; Counter # 0 of the 8253 CTC1 EQU 0FBDDH ; Counter # 1 of the 8253 ; ;----------------------------------------------------------------------- ; ; Main code starts here ; ;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 ; Spares for later use JP SPARE ; Spares for later use JP SPARE ; Spares for later use JP SPARE ; Spares for later use JP SPARE ; Spares for later use JP SPARE ; Spares for later use ; SPARE: RET ; ;----------------------------------------------------------------------- ; ; Screen print function ; SCRNPR: DS 0 ; ; <== Insert your own code here ; CALL PRINT DB 'This function not supported.',CR,LF DB 0 ; ; <== End of your own code ; RET ; ; Get a character from the modem: return in HL ; MCHIN: PUSH BC ; ; <== Insert your own code here ; LD BC,MSTAT ; MCHIN2: IN A,(C) ; Check for char waiting BIT RDA,A JR Z,MCHIN2 LD BC,MDATA IN A,(C) ; Read the character ; ; <== End of your own 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) ; ; <== Insert your own code here ; PUSH BC PUSH AF ; Save the character LD BC,MSTAT ; MCHOUT2:IN A,(C) ; Check for UART ready BIT TBE,A JR Z,MCHOUT2 POP AF ; Character in a LD BC,MDATA OUT (C),A ; Send it POP BC ; ; <== 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 ; PUSH BC LD BC,MSTAT LD HL,0 IN A,(C) BIT TBE,A ; Transmit buffer empty JR Z,MORDY1 INC HL ; MORDY1: DS 0 ; ; <== End of your own code ; POP BC 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 ; PUSH BC LD BC,MSTAT LD HL,0 IN A,(C) BIT RDA,A ; Received data available JR Z,MIRDY1 INC HL ; MIRDY1: DS 0 ; ; <== End of your own code ; POP BC 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 ; PUSH BC LD BC,MSTAT LD A,5 OUT (C),A LD A,BREAK ; F8h OUT (C),A LD HL,300 ; A 300 mS break CALL WAITHLMS LD A,5 OUT (C),A LD A,ONLINE ; 68h OUT (C),A LD A,3 OUT (C),A LD A,0E1H ; E1h OUT (C),A POP BC ; ; <== 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 ; PUSH BC LD BC,MSTAT LD HL,0 IN A,(C) AND A,ERROR JR Z,MDMER2 INC HL ; MDMER2: DS 0 ; ; <== End of your own code ; POP BC LD A,L ; Set/clear Z OR A RET ; ; Turn DTR ON ; DTRON: DS 0 ; ; <== Insert your own code here ; PUSH BC LD BC,MSTAT LD A,5 OUT (C),A LD A,(COMBYT) ; Get the one we used last time OR A,ONLINE ; 80h - set bit 7 high LD (COMBYT),A ; Save it for next time OUT (C),A ; Go POP BC ; ; ; <== End of your own code ; RET ; ; Turn DTR OFF ; DTROFF: DS 0 ; ; <== Insert your own code here ; PUSH BC LD BC,MSTAT LD A,5 OUT (C),A LD A,(COMBYT) ; Get the one we used last time AND ONHOOK ; 7Fh - clear bit 7 LD (COMBYT),A ; Save it for next time OUT (C),A ; Go POP BC ; ; <== End of your own code ; RET ; ; Initialise the SIO +++ ; The SIO is set up in four steps: ; ; 1) Reset ; 2) Reg 4 - clock, stop bits, parity ; 3) Reg 5 - dtr, Tx bits, Brk, TxEn, rts ; 4) Reg 3 - Rx bits, RxEn ; INIT: LD HL,2 ; Get parameters ADD HL,SP EX DE,HL CALL GETPARM ; In HL LD (BRATE),HL ; Baud rat 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 ; PUSH BC LD BC,MSTAT LD A,0 OUT (C),A ; Point to reg 0 LD A,18H ; Reset OUT (C),A ; *** step 1 LD A,4 ; Point to wrt reg 4 OUT (C),A LD E,44H ; Assume x16, 1 stop, No parity LD A,(STOP) ; Set stop bits CP 2 ; Set 2 if required JR NZ,SETPAR LD A,08H ; 0000 1000 OR E LD E,A ; SETPAR: LD A,(PARITY) ; Set parity bits CP 'O' JR NZ,SETPA2 LD D,01H ; 0000 0001 ODD JR SETPA3 ; SETPA2: CP 'E' JR NZ,SETPA4 LD D,03H ; 0000 0011 EVEN ; SETPA3: LD A,E OR A,D LD E,A ; SETPA4: LD A,E OUT (C),A ; *** step 2 LD A,5 ; Point to wrt reg 5 - dtr, Tx bits, etc OUT (C),A LD E,0EAH ; Assume dtr, TX 8 bits, TxEn, rts LD A,(DATA) CP 7 JR NZ,SETBI2 LD D,0BFH ; 1011 1111 7 bits LD A,E AND A,D LD E,A ; SETBI2: LD A,E OUT (C),A ; *** step3 LD A,3 ; Point to wrt reg 3 OUT (C),A LD E,0C1H ; Assume 8 bits LD A,(DATA) CP 7 JR NZ,SETBI3 LD D,07FH ; 0111 1111 7 bits LD A,E AND A,D LD E,A ; SETBI3: LD A,E OUT (C),A ; *** step 4 ; SETBRATE: PUSH IX ; Save IX LD DE,(BRATE) ; Get baud rate value (0-10) LD IX,BRVAL ADD IX,DE ADD IX,DE ; IX now points to the 2-byte value LD A,(IX) ; If zero, OR (IX+1) JR Z,SETBRX ; It's not valid LD BC,CTCONT LD A,36H OUT (C),A LD BC,CTC0 LD A,(IX) OUT (C),A ; Low byte LD A,(IX+1) OUT (C),A ; High byte LD BC,CTCONT LD A,76H OUT (C),A LD BC,CTC1 LD A,(IX) OUT (C),A ; Low byte LD A,(IX+1) OUT (C),A ; High byte LD A,(BRATE) ; Tell ZMP it's valid LD (MSPEED),A ; SETBRX: POP IX POP BC ; ; <== End of your own code ; RET ; BRATE: DW 5 ; Baud rate PARITY: DW 'N' ; Parity DATA: DW 8 ; Data bits STOP: DW 1 ; Stop bits COMBYT: DB 0EAH ; Save here ; ; Values for 8253 control reg for each baud rate: 0 if invalid ; BRVAL: DW 470H ; 110 0 DW 1A1H ; 300 1 DW 116H ; 450 2 DW 0D0H ; 600 3 DW 0B0H ; 710 4 DW 068H ; 1200 5 DW 034H ; 2400 6 DW 01AH ; 4800 7 DW 00DH ; 9600 8 DW 007H ; 19200 9 DW 0 ; 38400 10 DW 0 ; 57600 11 DW 0 ; 76800 12 DW 0 ; 115200 13 ; ; 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 Zenith Z19/Z29: 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,'Y',0 ; 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 ESC,'E',ESC,'H',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,'f',0 RET ; ; Turn on cursor ; SHOW: CALL PRINT DB ESC,'e',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 ; ; Initialise interrupt vectors ; INVEC: RET ; ; De-initialise interrupt vectors ; DINVEC: RET ; ; User-defined entry routine: leave empty if not used ; USERIN: RET ; ; User-defined exit routine: leave empty if not used ; USEROUT:RET ; ;------------------- 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