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-TV05.Z80
< prev
next >
Wrap
Text File
|
2000-06-30
|
14KB
|
704 lines
; PROGRAM: ZMO-TV05.Z80
; AUTHOR: Michael Evenson
; VERSION: 1.5
; DATE: 10 Nov, 1988
;-----------------------------------------------------------------------
; This overlay is set up for Televideo TS80x(H) using modem port.
; Uses a Z80SIO AND A Z80CTC.
; flags must be set for Televideo TS806, TS816, or TS802(H)
; currently does not support TS803 (STI) or TS804 (MPM system)
;-----------------------------------------------------------------------
; 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/11/10 - First version of this file - Michael Evenson
;
; 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 00145H ; origin of this overlay
; This address should remain constant
; with subsequent revisions.
MSPEED EQU 003CH ; current baud rate id
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
; be sure to set the correct system and port identifier here
; (only one of each please)
TS802 EQU YES
TS806 EQU NO
TS816 EQU NO
MODEMP EQU YES
PRINTP EQU NO
;
ESC EQU 1BH
CTRLQ EQU 11H
CR EQU 0DH
LF EQU 0AH
BDOS EQU 5
; Televideo specific equates ******************************************
IF TS802
IF MODEMP
MDATA EQU 020H
MSTAT EQU 022H
CTC EQU 08H
ELSE
MDATA EQU 021H
MSTAT EQU 023H
CTC EQU 09H
ENDIF
ELSE
IF TS806
IF MODEMP
MDATA EQU 050H
MSTAT EQU 052H
CTC EQU 80H
ELSE
MDATA EQU 051H
MSTAT EQU 053H
CTC EQU 81H
ENDIF
ELSE
IF TS816
IF MODEMP
MDATA EQU 059H ; channel B
MSTAT EQU 05BH
CTC EQU C1H ; CTC 1
ELSE
MDATA EQU 058H ; channel A
MSTAT EQU 05AH
CTC EQU C0H ; CTC 0
ENDIF
ENDIF
ENDIF
ENDIF
RDA EQU 0
TBE EQU 2
MODE EQU 47H
ONHOOK EQU 7FH
ONLINE EQU 80H
ERROR EQU 70H
BREAK EQU 0F8H
RESET EQU 30H
; ******************************************
; Main code starts here
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 ; 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:
; <== Insert your own code here
CALL PRINT
DB 'This function not supported.',CR,LF,0
; <== End of your own code
RET
;Get a character from the modem: return in HL
MCHIN:
PUSH BC
; <== Insert your own code here
MCHIN2:
IN A,(MSTAT) ; check for char waiting
BIT RDA,A
JR Z,MCHIN2
IN A,(MDATA) ; read the char
; <== 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
LD B,A ; save the char
MCHOUT2:
IN A,(MSTAT) ; check for uart ready
BIT TBE,A
JR Z,MCHOUT2
LD A,B ; char in a
OUT (MDATA),A ; send it
POP BC
; <== End of your own code
RET ; done
;Test for output ready: return TRUE (1) in HL if ok
MORDY:
; <== Insert your own code here
LD HL,0
IN A,(MSTAT)
BIT TBE,A ; transmit buffer empty
JR Z,MORDY1
INC HL
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
LD HL,0
IN A,(MSTAT)
BIT RDA,A ; received data available
JR Z,MIRDY1
INC HL
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
LD A,5
OUT (MSTAT),A
LD A,BREAK ; F8
OUT (MSTAT),A
LD HL,300 ; wait 300 mS
CALL WAITHLMS
LD A,5
OUT (MSTAT),A
LD A,ONLINE ; 68
OUT (MSTAT),A
LD A,3
OUT (MSTAT),A
LD A,0E1H
OUT (MSTAT),A ; E1
; <== End of your own code
RET
;
;Test UART flags for error: return TRUE (1) in HL if error.
MDMERR:
; <== Insert your own code here
LD HL,0
IN A,(MSTAT)
AND ERROR
JR Z,MDMER2
INC HL
MDMER2:
; <== End of your own code
LD A,L ; set/clear Z
OR A
RET
;Turn DTR ON
DTRON:
; <== Insert your own code here
LD A,5
OUT (MSTAT),A
LD A,(COMBYT) ; get the one we used last time
OR ONLINE ; 80h - set bit 7 high
LD (COMBYT),A ; save it for next time
OUT (MSTAT),A ; go
; <== End of your own code
RET
;Turn DTR OFF
DTROFF:
; <== Insert your own code here
LD A,5
OUT (MSTAT),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 (MSTAT),A ; go
; <== 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 rate
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 A,0
OUT (MSTAT),A ; point to reg 0
LD A,18H ; reset
OUT (MSTAT),A ; *** step 1
LD A,4 ; point to wrt reg 4
OUT (MSTAT),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
SET 3,E
SETPAR:
LD A,(PARITY) ; set parity bits
CP 'O'
JR NZ,SETPA2
SET 0,E ; ODD
JR SETPA3
SETPA2: CP 'E'
JR NZ,SETPA3
SET 0,E
SET 1,E ; EVEN
SETPA3: LD A,E
OUT (MSTAT),A ; *** step 2
LD A,5 ; point to wrt reg 5 - dtr, Tx bits, etc
OUT (MSTAT),A
LD E,0EAH ; assume dtr, TX 8 bits, TxEn, rts
LD A,(DATA)
CP 7
JR NZ,SETBI2
RES 6,E ; 7 bits
SETBI2: LD A,E
OUT (MSTAT),A ; *** step 3
LD A,3 ; point to wrt reg 3
OUT (MSTAT),A
LD E,0C1H ; assume 8 bits
LD A,(DATA)
CP 7
JR NZ,SETBI3
RES 7,E ; 7 bits
SETBI3: LD A,E
OUT (MSTAT),A ; *** step 4
SETBRATE:
LD DE,(BRATE) ; get baud rate value (0-10)
LD HL,BRVAL
ADD HL,DE
LD A,(HL) ; get value from table
OR A ; 0 = not valid
JR Z,SETBRX ; so quit
LD A,MODE ; 47h
OUT (CTC),A ; select the correct timer and mode of the CTC
LD A,(HL) ; then get value back
OUT (CTC),A ; do it
LD A,(BRATE)
LD (MSPEED),A ; tell zmp it's ok
SETBRX:
POP BC
RET
BRATE: DW 7 ; baud rate:
PARITY: DW 'N' ; parity
DATA: DW 8 ; data bits
STOP: DW 1 ; stop bits
COMBYT: DB 0EAH ; save it here
;Values for Z80CTC control reg for each baud rate: 0 if invalid
BRVAL:
DB 0 ; 110 0
DB 80H ; 300 1
DB 0 ; 450 2
DB 40H ; 600 3
DB 0 ; 710 4
DB 20H ; 1200 5
DB 10H ; 2400 6
DB 08H ; 4800 7
DB 04H ; 9600 8
DB 02H ; 19200 9
DB 0 ; 38400 10
DB 0 ; 57600 11
DB 0 ; 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: these are for Televideo TS950: 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 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 ESC,'*',0
RET
;Inverse video on:
INVON:
CALL PRINT
DB ESC,'G4',0
RET
;Inverse video off:
INVOFF:
CALL PRINT
DB ESC,'G0',0
RET
;Turn off cursor:
HIDE:
CALL PRINT
DB ESC,'.1',0
RET
;Turn on cursor:
SHOW:
CALL PRINT
DB ESC,'.2',0
RET
;Save cursor position:
SAVECU:
RET
;Restore cursor position:
RESCU:
RET
;User-defined entry routine: leave empty if not used
USERIN:
RET
;User-defined exit routine: leave empty if not used
USEROUT:
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 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
;
;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 too large!
ENDIF
END