;
;TITLE 'SENDOUT UTILITY FOR CP/M AND PMMI MODEM 4/8/81 AAJ'
;
;THIS ROUTINE WRITTEN BY AL JEWER AND RELEASED IN PUBLIC
;DOMAIN 4/8/81. 
;
;THIS CP/M TRANSIENT COMMAND IS INVOKED IN THIS MANNER:
;
;A>SENDOUT XMODEM S FILENAME.TYP
;
;IN THIS EXAMPLE, THE STRING "XMODEM S FILENAME.TYP"
;WILL BE SENT OUT THE MODEM PORT TO A REMOTE SYSTEM.
;THIS IS FOR USE IN:
;
;		1) TRANSFERRING MULTIPLE PROGRAMS TO & FROM
;			REMOTE USING A SUBMIT FILE
;
;		2) SENDING COMMANDS WITHOUT HAVING TO
;			ENTER & EXIT THE "MODEM" PROGRAM
;
;THE STRING CAN BE UP TO 127 CHARACTERS LONG, AND IS 
;ECHOED TO THE LOCAL CONSOLE AS IT IS SENT.
;
;THE PROGRAM WILL WAIT FOR A ">" CHARACTER BEFORE IT
;SENDS THE LINE, TO ALLOW THE REMOTE TO BE READY FOR
;THE COMMAND LINE. AS THE LINE IS SENT, THE PROGRAM 
;WILL CHECK THE CHARACTERS ECHOED BACK TO ASSURE THAT
;THE COMMAND LINE HAS BEEN TRANSMITTED PROPERLY.
;IF AN ERROR IS DETECTED, THE PROGRAM WILL SEND OUT
;A ^U FOLLOWED BY A CARRIAGE RETURN, THEN RETRY 
;SENDING THE LINE, UNTIL A PROPER TRANSMISSION IS MADE.
;
;UPDATES: (IN REVERSE ORDER TO MINIMIZE READING TIME)
;
;10-APR-81 REWRITTEN BY AL JEWER TO CHECK ECHOED
;	   STRING FOR VALID TRANSFER.
;
;08-APR-81 MODIFIED BY TOM JORGENSON FOR SUPPORT
;	   OF OTHER MODEM/PORT TYPES (ESP. H89)
;
;ANY QUESTIONS OR COMMENTS:
;
;	AL JEWER
;	PO BOX 123
;	WHITEWATER, WI. 53190
;
;	473-7263 (HOME)
;	563-9539 (WORK)
;
;BASE DEFINITION, CHANGE THIS TO 4200H IF ALTERNATE CP/M
;(RELOCATED) VERSION SUCH AS HEATH/LIFEBOAT OR TRS-80
;
BASE	EQU	0	;BASE OF MEMORY SEGMENT
;
;THESE SHOULD BE O.K. AS IS
;
BOOT	EQU	BASE	;JUMP HERE TO REBOOT CP/M
BDOS	EQU	BASE+5	;BDOS FUNCTION CALL ADDRESS
BUFFER	EQU	BASE+80H ;INPUT LINE BUFFER
CONOUT	EQU	2	;BDOS PRINT FUNCTION CODE
CR	EQU	0DH	;ASCII CHARACTERS
LF	EQU	0AH
CTLU	EQU	'U'-40H
;
FALSE	EQU	0
TRUE	EQU	NOT FALSE
;
FASTCLK	EQU	TRUE	;TRUE IF 4MHZ OR GREATER
;
;CHOOSE YOUR MODEM/PORT TYPE HERE:
;
H89	EQU	FALSE	;TRUE, IF H89
PMMI	EQU	TRUE 	;TRUE, IF PMMI
;
	IF	PMMI
;
;CHANGE THE FOLLOWING IF YOUR PMMI IS NOT AT THE 
;STANDARD BASE ADDRESS OF 0C0H.
;
TPORT	EQU	0C0H	;THIS IS STATUS PORT
DPORT	EQU	TPORT+1	;DATA I/O PORT
POTBMT	EQU	1	;XMIT BUFFER EMPTY FLAG
PODAV	EQU	2	;DATA AVAILABLE FLAG
;
	ENDIF		;PMMI
;
	IF	H89
;
;SHOULD USE THESE AS LONG AS YOU CONFORM
;TO STD PORT ADDRESS (330Q)
;
TPORT	EQU	335Q	;STATUS PORT (8250 UART)
DPORT	EQU	330Q	;DATA PORT
POTBMT	EQU	040Q	;THRE BIT (TX BUFFER EMPTY)
PODAV	EQU	001Q	;DATA AVAILABLE FLAG
;
	ENDIF		;H89
;
;
ORG	BASE+100H	;START OF TPA
;
START:	LXI	SP,STACK ;SET SAFE STACK
	JMP	PDATA	;JUMP TO TEST CURRENT CHARACTER
;
PIN:	LXI	B,0	;COUNTER TO B
;
PLOOP:	DCX	B	;COUNT THE LOOP
	MOV	A,B	;CHECK FOR DONE
	ORA	C
	JZ	TRYAGN	;JUMP IF TIMED OUT
;
	IF	FASTCLK
	XTHL		;WASTE TIME IF AT 4 MHZ
	XTHL
	XTHL
	XTHL
	ENDIF		;FASTCLK
;
PL2:	IN	TPORT	;GET THE STATUS PORT
	ANI	PODAV	;WE GOT A CHARACTER?
	JZ	PLOOP	;LOOP TILL TIMEOUT OR DATA RECEIVED
;
PDATA:	IN	DPORT	;GET THE CHARACTER
	ANI	7FH	;DROP PARITY BIT JUST IN CASE
	MOV	E,A	;ECHO IT TO THE CRT
	CALL	CRTOUT
	CPI	'>'	;DISK PROMPT?
	JNZ	PIN	;LOOP TILL PROPER CHARACTER RECEIVED
;
;WE HAVE NOW RECEIVED A ">" CHARACTER, SO THE REMOTE SYSTEM
;IS READY TO RECEIVE THE COMMAND LINE.
;
	LXI	H,BUFFER ;POINT TO COMMAND LINE BUFFER
	MOV	B,M	;GET THE CHARACTER COUNT
	MOV	A,B	;ALSO TO A REGISTER
	ORA	A	;ZERO LENGTH?
	JZ	BOOT	;RETURN IF SO
	DCR	A	;LENGTH OF 1? (THIS WOULD BE SPACE ONLY)
	JZ	BOOT	;IGNORE THIS TOO
	INR	B	;ADD 1 FOR FINAL CR
	INX	H	;SKIP THE LEADING SPACE
;
LOOP:	INX	H	;POINT TO NEXT CHARACTER
	DCR	B	;COUNT THE CHARACTER
	JNZ	NOTDUN	;JUMP IF NOT FINISHED
	MVI	E,LF	;SEND LINE FEED TO LOCAL CONSOLE
	CALL	CRTOUT
	JMP	BOOT	;DONE!
;
NOTDUN:	MVI	A,1	;CHECK FOR LAST CHARACTER
	CMP	B
	JNZ	GO	;JUMP IF NOT LAST ONE
	MVI	M,CR	;MAKE LAST CHARACTER CARRIAGE RETURN
;
GO:	MOV	C,M	;GET CHARACTER
	CALL	POUT	;SEND OUT THE MODEM
	LXI	D,0	;TIME COUNTER TO D
;
RECLP:	IN	TPORT	;CHECK FOR CHARACTER
	ANI	PODAV	;CHARACTER RECEIVED?
	JNZ	GOTONE	;JUMP IF WE GOT A CHARACTER
	DCX	D	;COUNT THE TIMER
	MOV	A,D
	ORA	E
	JZ	TRYAGN	;JUMP IF TIMED OUT
;
	IF	FASTCLK
	XTHL		;WASTE TIME ON FAST SYSTEMS
	XTHL
	XTHL
	XTHL
	ENDIF		;FASTCLK
;
	JMP	RECLP	;CONTINUE WAITING
;	
GOTONE:	IN	DPORT	;GET THE CHARACTER
	ANI	7FH	;DROP PARITY
	MOV	E,A
	CALL	CRTOUT	;DISPLAY TO LOCAL CONSOLE
	CMP	M	;IS IT THE SAME AS WHAT WE SENT?
	JZ	LOOP	;JUMP IF OK
;
TRYAGN:	MVI	C,CTLU	;CANCEL THE LINE
	CALL	POUT
	MVI	C,CR	;THEN GET NEW PROMPT
	CALL	POUT
	JMP	PIN
;
POUT:	IN	TPORT	;GET PHONE STATUS PORT
	ANI	POTBMT	;MASK FOR XMIT BUFFER EMPTY
	JZ	POUT	;WAIT FOR PHONE
	MOV	A,C	;SEND THE CHARACTER
	OUT	DPORT
	RET
;
CRTOUT:	PUSH	H	;SAVE AFFECTED REGISTERS
	PUSH	B
	PUSH	PSW
	MVI	C,CONOUT
	CALL	BDOS	;SEND TO CONSOLE
	POP	PSW
	POP	B
	POP	H
	RET
;
	DS 32		;STACK AREA
STACK	EQU	$
;
	END	START
