;
;  Program:	DEMOPORT.ASM
;  Author:	Rob Wood
;		c/o ANKOR
;		P. O. Box 210089
;		Anchorage, Alaska  99521-0089
;  Version:	1.0
;  Date:	03 APR 87
;
;==============================================================================
;
;	DEMOPORT was written for use by ANKOR, the Alaska Network for Kaypro
;	Owner Resources, a KAYPRO user group in Anchorage, Alaska and may
;	be used freely by any other user groups or KAYPRO owners.
;
;	This program was written for the Kaypro 10-83 and should be easily
;	modified for any of the other CP/M Kaypros.  DemoPort is used with 
;	the "Octopus" described in September 1984 issue of "Profiles".  It
;	allows live demonstrations by sending all characters out the modem
;	port and then to the screen.  This allows the other machines on the
;	"Octopus" to receive via TERM or other modem program what is being
;	seen on the main demonstration machines screen.  DemoPort does not
;	scan for incoming characters from the other machines.
;
;	When you run DemoPort, a small program is moved to the restart vector
;	table starting at location 0008h in memory.  The modem port is
;	initialized and the CONOUT vector is redirected to the small program.
;	The small program will send the characters sent to the CONOUT routine
;	out the modem port and then pass them on to CONOUT for display on the
;	screen.  You have to set the desired baud rate to be use for the modem
;	port before you execute DemoPort.  When DemoPort is run again,
;	the CONOUT vector is restored returning console output to just the
;	screen.			
;	
;	Remember, only characters sent to the screen using the CONOUT routine
;	will be sent out the modem port.
;
;	Use ASM to compile and LOAD to convert the .HEX file to the .COM
;	file.  (ASM and LOAD equivalent programs may be used.)
;
;	DemoPort is a variation and improvement on E. L. Bergh's DualPort
;	program.
;
;==============================================================================
;
;  equates
;
BOOT	EQU	0		; System warm boot vector
IOBYTE	EQU	3		; I/O byte
BDOS	EQU	5		; Bdos function call vector
CONOT	EQU	9		; Offset to conout vector
SMALL	EQU	0008H		; Memory location to load small program
CR	EQU	13		; Carrage return
LF	EQU	10		; Line feed
;
;  modem port addresses
;
SIOCPA	EQU	6		; Serial channal a/b control/status port
SIODPA	EQU	4		; Serial channal a data port

	ORG	0100H		;* Comment out if using M80/L80

	JMP	START
;
;  small program that is loaded into low memory to output
;  characters to output port then to console
;
SMALLP:	IN	SIOCPA		; Get output port status
	ANI	4		; Get busy bit
	JZ	SMALL		; If busy then loop till not busy
	MOV	A,C		; Load character to output
	OUT	SIODPA		; Output character to port
CALL2:	CALL	0		; Call conout routine to ouput to console
	RET			; Return to calling program
SLEN	EQU	$-SMALLP	; Calculate length of small program
;
;  start of program
;
START:	LHLD	BOOT+1		; Get the address of warm boot vector
	LXI	D,CONOT+1	; Calculate location of conout vector
	DAD	D

	MOV	E,M		; Get the conout address
	INX	H
	MOV	D,M

	DCX	H		; Fix pointer to start
	PUSH	H		; Save conout address

	LXI	B,SMALL		; Check to see if demoport is on by
	MOV	A,B		; Comparing the current conout vector
	CMP	D		; With the starting address of the
	JNZ	ON		; Small program.  if conout vector same
	MOV	A,C		; As small program address, then restore
	CMP	E		; Conot vector else load small program
	JNZ	ON
;
;  turn demoport off if it is now on
;
OFF:	LXI	D,MSG1		; Set message pointer to "off" message
	MVI	C,9		; Bdos output function
	CALL	BDOS		; Print message to port and console
	LXI	D,MSGOFF
	MVI	C,9
	CALL	BDOS
	LXI	D,MSG2
	MVI	C,9
	CALL	BDOS

	LHLD	1+SMALL+CALL2-SMALLP ; Get conout vector from small program
	XCHG			; Move to de registers
	POP	H		; Get conout vector address
	MOV	M,E		; Move conout vector to conout vector address
	INX	H
	MOV	M,D

	JMP	DONE		; All done....
;
;  turn demoport on if it is now off
;
ON:	XCHG			; Get the conout address in (hl)
	SHLD	CALL2+1		; Patch call to conout in small program

	LXI	D,SMALLP	; Starting address of small program
	LXI	H,SMALL		; Address in low memory to load small program
	MVI	B,SLEN		; Length of small program

MOVEP	EQU	$		; Move small program loop
	LDAX	D
	MOV	M,A
	INX	D
	INX	H
	DCR	B
	JNZ	MOVEP

	POP	H		; Restore bios-conout address
	LXI	D,SMALL		; Where to pass control
	MOV	M,E
	INX	H
	MOV	M,D		; Patch the bios-conout address to point
				; To the small program in low memory

INIT:	LXI	H,TABLE		; Get address of init data table
	MOV	B,M		; Get size of table
INITLP:	INX	H		; Increment to next element of table
	MOV	A,M		; Get element
	OUT	SIOCPA		; Ouput to sio status channel
	DCR	B		; Decrease element counter
	JNZ	INITLP		; Loop until all elements output

	LXI	D,MSG1		; Set message pointer to "on" message
	MVI	C,9		; Bdos print message function code
	CALL	BDOS		; Print message to port and console
	LXI	D,MSGON
	MVI	C,9
	CALL	BDOS
	LXI	D,MSG2
	MVI	C,9
	CALL	BDOS

DONE:	RET			; All done, return to system
;
;  messages
;
MSG1:	DB	26,CR,LF
	DB	'DEMOPORT v3.1 - KAYPRO Demo display now ','$'

MSG2:	DB	'-------------------------------------------',CR,LF
	DB	07,CR,LF,'$'

MSGON:	DB	'ON.',CR,LF,'$'

MSGOFF:	DB	'OFF.',CR,LF,'-','$'
;
;  table for init of sio port
;
TABLE:	DB	9		; Number of entries in table to output
	DB	18H		; Channel reset to sio
	DB	4,44H		; Wr4: clock divider, 1 stop bit, no parity
	DB	1,0		; Wr1: no inerrupts
	DB	3,0C1H		; Wr3: 8 bits/ch, no auto enable, enable rcvr
	DB	5,0EAH		; Wr5: 8 bits/ch, set dtr and rts

	END
