home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
CPM
/
MODEMS
/
ZMODEM
/
ZMO-CP05.Z80
< prev
next >
Wrap
Text File
|
2000-06-30
|
14KB
|
725 lines
; 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