;LBSETCOM/ASM - Set RS232 Parameters
	TITLE	<SETCOM - LS-DOS 6.2>
;
;	Data area offsets
;
OFFSET	EQU	4
MSMASK	EQU	OFFSET+0
UCIMAGE	EQU	OFFSET+1
BAUDRT	EQU	OFFSET+2
BRK	EQU	OFFSET+3
;
;	Default settings
;
DEFMS	EQU	000H
DEFUC	EQU	0A5H
DEFBA	EQU	055H
DEFBR	EQU	003H
;
;	ASCII/init equivalences
;
_INIT	EQU	02H		;Ctl value to init driver
_ETX	EQU	03H
_CR	EQU	0DH
_LF	EQU	0AH
_APOS	EQU	27H
PAR_ERR	EQU	44		;Parameter Error
;
;	@PARAM evaluation types
;
FLAG	EQU	01000000B
ABB	EQU	00010000B
NUM	EQU	10000000B
STR	EQU	00100000B
;
*GET	SVCMAC:3		;SVC Macro equivalents
;
	ORG	2400H
;
BEGIN	EQU	$
	LD	(SAVESP+1),SP	;Save entry stack
	CALL	PGRM		;Perform operations
;
;	Set up exit condition
;
$EXIT	LD	HL,0		;No errors
SAVESP	LD	SP,$-$		;P/u original SP
	@@CKBRKC		;Clear <BREAK>
	RET
;
;	Abort program
;
$ABORT	LD	HL,-1		;Init error return
	JR	SAVESP		;Exit program
;
;	Display char in C
;
$DSP	@@DSP			;Display
	RET	Z		;Return if NO error
	JR	IOERR		;  else error
;
;	Display text @ (HL)
;
$DSPLY	@@DSPLY			;Display
	RET	Z		;Return if NO error
;
;	I/O error, display what
;
IOERR	LD	L,A		;Save error code
	OR	0C0H		;Set return+short message
	LD	C,A		;Pass error code
	@@ERROR			;Display error
;
ERROR$	LD	H,0		;Set exit code
	JR	SAVESP		;Terminate program
;
BADMOD	LD	HL,BADDCB	;'COM/DVR not installed'
	@@LOGOT			;Log error
	LD	L,8		;'device not available'
	JR	ERROR$		;Return error in HL
;
;	Parameter error
;
PRMERR	LD	A,PAR_ERR	;"Parameter Error"
	JP	IOERR		;Abort
;
;	PGRM - Set up RS-232 Parameters
;
PGRM	EQU	$
;
	IF	@MOD4
	PUSH	HL		;Save command line pntr
	LD	DE,MDNAME	;$CL name header
	@@GTMOD			;Find module header
	JR	NZ,BADMOD	;Exit if not found
	PUSH	DE		;Pass pointer to IX
	POP	IX		;IX=>next byte after
	POP	HL		;Rcvr cmdline ptr
	ENDIF
;
;	Check if any parameters entered
;
	DEC	HL		;Setup for immed INC
SPLP	INC	HL		;Bump to next char
	LD	A,(HL)		;Fetch input char
	CP	' '		;Space?
	JR	Z,SPLP		;Ignore if space
	CP	'('		;Param marker?
	JP	NZ,SHOW		;No, show settings 
;
	LD	DE,PRMTBL$	;Parameter table
	@@PARAM			;Evaluate user input
	JP	NZ,PRMERR	;Go if parameter error
;
	IF	@MOD2
	LD	A,(PORTP)	;Get port param
	OR	A		;Anything input?
	LD	DE,MDNAME1	;$CL
	JR	Z,PORTF		;Go default
	LD	BC,(PORTD)	;Get port value
	INC	B		;Test msb
	DEC	B
	JR	NZ,PRMERR	;Param error if >256
	LD	A,C		;Get lsb
	OR	A		;0?
	JR	Z,PRMERR	;Go if yes
	DEC	A		;1?
	JR	Z,PORTF		;Yes, $CL
	DEC	A		;2?
	JR	NZ,PRMERR	;Param error if not
	LD	DE,MDNAME2	;$CM
PORTF	@@GTMOD			;Locate it
	JR	NZ,BADMOD	;Go if not found
	PUSH	DE		;Else pass to IX
	POP	IX		;IX => block
	ENDIF
;
;	Check if DEFAULT param entered
;
	LD	DE,(DFPARM)	;Check D parm
	LD	A,D
	OR	E
	CALL	NZ,DEFALT	;Go if Default parm used
;
	LD	DE,(QPARM)	;Query parm used?
	LD	A,D		;Check input
	OR	E
	JP	Z,CKPARM	;Check input if not query
;
;	Prompt user for input not entered on command line
;
;	Fetch BAUD
;
ASKBAUD	LD	HL,DMSG2	;BAUD param display
	LD	DE,BTYP		;BAUD param
	CALL	GETIT		;Get user input
	JR	NC,ASKWORD	;Continue on ENTER
	CALL	CKBAUD		;Test response for valid
	JR	Z,ASKWORD	;Move on if valid entry
BADBAUD	XOR	A		;  else clear
	LD	(BRESP),A	;  for re-try
	JR	ASKBAUD		;Bad entry - retry
;
;	Fetch WORD
;
ASKWORD	LD	HL,DMSG3	;WORD display
	LD	DE,WTYP		;Param type
	CALL	GETIT		;Get user input
	JR	NC,ASKSTOP	;Nil input, leave it
	LD	A,(WORDP)	;Fetch input
	CP	5		;<5?
	JR	C,BADWORD	;Bad entry
	CP	8+1		;>8?
	JR	C,ASKSTOP	;Go if OK
BADWORD	XOR	A		;Clear param
	LD	(WRESP),A	;Load flag
	JR	ASKWORD		;Re-try
;
;	Fetch STOP
;
ASKSTOP	LD	HL,DMSG4	;STOP
	LD	DE,STYP		;=>type byte
	CALL	GETIT		;Get user input
	JR	NC,ASKPAR	;Nil input, leave it
	LD	A,(STOPP)	;Chk range
	OR	A		;0?
	JR	Z,BADSTOP	;Invalid if yes
	CP	2+1		;>2?
	JR	C,ASKPAR	;Go if OK
BADSTOP	XOR	A		;Load zero
	LD	(SRESP),A	;Clear input param
	JR	ASKSTOP		;Ask again
;
;	Fetch PARITY
;
BADPAR	XOR	A		;Load zero
	LD	(PRESP),A	;Clear response byte
ASKPAR	LD	HL,DMSG5	;PARITY display driver
	LD	DE,PTYP		;Param type
	CALL	GETIT		;Get user input
	JR	NC,ASKBRK	;Nil input, leave
;
;	Check if user entered 'O' or 'E' or ON/OFF
;
	LD	A,(PRESP)	;Get response byte
	LD	DE,(PARITYP)	;Get param pointer
	BIT	6,A		;Switch?
	JR	NZ,ASKBRK	;Yes, continue
;
;	Check for ODD/EVEN input
;
	LD	A,(DE)		;Get input
	CALL	UCASE		;Make upper case
	CP	'E'		;Even?
	JR	Z,ASKBRK	;Continue if yes
	CP	'O'		;Odd?
	JR	NZ,BADPAR	;Invalid, re-prompt
;
;	Fetch BREAK
;
ASKBRK	LD	HL,DMSG6	;Display driver
	LD	DE,BRTYP	;Param type
	CALL	GETIT		;Get user input
;
;	Fetch DTR
;
ASKDTR	LD	HL,DMSG8	;Display driver
	LD	DE,DTYP		;Param type
	CALL	GETIT		;Get user input
;
;	Fetch RTS
;
ASKRTS	LD	HL,DMSG9	;Display driver
	LD	DE,RTYP		;Param type
	CALL	GETIT		;Get user input
;
;	Fetch RI
;
ASKRI	LD	HL,DMSG11	;Display driver
	LD	DE,RITYP	;Param type
	CALL	GETIT		;Get user input
;
;	Fetch DSR
;
ASKDSR	LD	HL,DMSG12	;Display driver
	LD	DE,DSTYP	;Param type
	CALL	GETIT		;Get user input
;
;	Fetch CD
;
ASKCD	LD	HL,DMSG13	;Display driver
	LD	DE,CDTYP	;Param type
	CALL	GETIT		;Get user input
;
;	Fetch CTS
;
ASKCTS	LD	HL,DMSG14	;Display driver
	LD	DE,CTTYP	;Param type
	CALL	GETIT		;Get user input
;
;	Check params and issue INIT to device
;
CKPARM	CALL	SETPARAM	;Check entered params
	LD	E,(IX+0)	;Pickup DCB address lsb
	LD	D,(IX+1)	;Pickup DCB address msb
	LD	C,_INIT		;Init code
	@@CTL			;Setup channel for values
	RET			;Completed
;
;	Display drivers for text
;
DMSG1	LD	HL,MSG1		;RS232 params:
	CALL	$DSPLY		;Display and return
	LD	(HL),_LF	;Set for next time
	RET
;
DMSG2	LD	HL,MSG2		;BAUD=
	CALL	$DSPLY		;Display
	LD	A,(IX+BAUDRT)	;Get baud rate
	AND	0FH		;Low 4 bits only
	ADD	A,A		;*2
	LD	HL,BAUDTBL	;Baud lookup table
	ADD	A,L		;Add to lsb table
	LD	L,A		;Update lsb table
	JR	NC,$+3		;Go if no page cross
	INC	H		;  else bump page
	LD	A,(HL)		;Get LSB baud
	INC	HL		;Bump table pointer
	LD	H,(HL)		;Get MSB baud
	LD	L,A		;HL = baud rate
	LD	DE,MSG20	;Text to load
	@@HEXDEC		;Convert to decimal
	LD	A,_ETX		;End text char
	LD	(DE),A		;Terminate text
;
;	Strip leading zeroes from display
;
	LD	HL,MSG20	;Text loaded
	LD	A,' '		;Test char
STRIP1	CP	(HL)		;Leading zero?
	INC	HL		;Bump pointer
	JR	Z,STRIP1	;Go till non-zero found
	DEC	HL		;Adjust pointer
	JP	$DSPLY		;Display remainder
;
DMSG3	LD	HL,MSG3		;WORD=
	CALL	$DSPLY		;Display header
	LD	A,(IX+UCIMAGE)	;Get data
	RLCA			;Align to low bits
	RLCA
	RLCA
	AND	3		;2 bits only
	JP	PE,$+5		;Go if set
	XOR	3		;Else reverse 6/7
	ADD	A,5+'0'		;Correct + ASCII
	LD	C,A		;Pass character
	JP	$DSP		;Display and return
;
DMSG4	LD	HL,MSG4		;STOP=
	CALL	$DSPLY		;Display header
	LD	C,'1'		;Set one bit
	BIT	4,(IX+UCIMAGE)	;Get data
	JR	Z,$+3		;Go if one stop
	INC	C		;Else bump to '2'
	JP	$DSP		;Display and return
;
DMSG5	LD	HL,MSG5		;PARITY=
	CALL	$DSPLY		;Display
	LD	HL,MSG16	;OFF
	BIT	3,(IX+UCIMAGE)	;Is off?
	JP	NZ,$DSPLY	;Yes, go
	LD	HL,MSG17	;ODD
	BIT	7,(IX+UCIMAGE)	;Is odd?
	JR	Z,$+5		;Go if yes
	LD	HL,MSG18	;EVEN
	JP	$DSPLY		;Display and return
;
DMSG6	LD	HL,MSG6		;BREAK=
	CALL	$DSPLY		;Display header
	LD	C,(IX+BRK)	;Get break char
	LD	HL,MSG21A	;Text to load
	@@HEX8			;Convert to ASCII
	LD	HL,MSG21	;Text start
	JP	$DSPLY		;Display and return
;
DMSG7	LD	HL,MSG7		;Input:
	JP	$DSPLY		;Display and return
;
DMSG8	LD	HL,MSG8		;DTR=
	CALL	$DSPLY		;Display
	BIT	1,(IX+UCIMAGE)	;Is on?
	JR	DMSG89		;Display
;
DMSG9	LD	HL,MSG9		;RTS=
	CALL	$DSPLY		;Display header
	BIT	0,(IX+UCIMAGE)	;Is on?
;
DMSG89	LD	HL,MSG15	;ON?
	JR	Z,$+5		;Go if yes
	LD	HL,MSG16	;OFF
	JP	$DSPLY		;Display and return
;
DMSG10	LD	HL,MSG10	;Output:
	JP	$DSPLY		;Display and return
;
DMSG11	LD	HL,MSG11	;RI=
	LD	A,00010001B	;Enable bits
	JR	DMSG0		;Go common
;
DMSG12	LD	HL,MSG12	;DSR=
	LD	A,01000100B	;Enable bits
	JR	DMSG0		;Go common
;
DMSG13	LD	HL,MSG13	;CD=
	LD	A,00100010B	;Enable bits
	JR	DMSG0		;Go common
;
DMSG14	LD	HL,MSG14	;CTS=
	LD	A,10001000B	;Enable bits
;
DMSG0	PUSH	AF		;Save bits
	CALL	$DSPLY		;Display prefix
	POP	AF		;Restore
	AND	(IX+MSMASK)	;And with mask
	LD	HL,MSG19	;IGNORE
	JR	Z,DMSG0X	;Go if yes
	LD	HL,MSG15	;ON
	JP	PO,DMSG0X	;Go if yes
	LD	HL,MSG16	;OFF
DMSG0X	JP	$DSPLY		;Display and return
;
DMSG22	LD	HL,MSG22	;CR
	JP	$DSPLY		;Display and return
;
DMSG23	LD	HL,MSG23	;', '
	JP	$DSPLY		;Display and return
;
;	Display entire parameter set
;
DSPALL	PUSH	IY		;Save
	LD	IY,DSPTBL	;Display table
DSPSET	LD	L,(IY+0)	;Get lsb vector
	LD	H,(IY+1)	;Get msb vector
	LD	A,H		;Check for term
	OR	L		;HL = 0000?
	JR	Z,DSPDONE	;Yes, go
	PUSH	HL		;Save address
	LD	HL,DSPRET	;Return vector
	EX	(SP),HL		;Leave return, get vector
	JP	(HL)		;Display
DSPRET	INC	IY		;Bump table
	INC	IY		;2 byte entries
	JR	DSPSET		;Continue
DSPDONE	POP	IY		;Restore
	RET			;Display complete
;
;	QUERYing for parameter
;
GETIT	PUSH	HL		;Save display driver
	PUSH	DE		;Save type byte
	EX	DE,HL		;Type byte to HL
	CALL	CKRSP		;Check if response enterd
	POP	DE		;Restore type byte
	POP	HL		;Restore prompt
	RET	NZ		;Already have this one
;
;	Setup for prompt display
;
	PUSH	HL		;Save for repeat prompt
	PUSH	DE
	CALL	GETRSP		;Get user response
	POP	DE		;Restore data
	POP	HL
	JR	NZ,GETIT	;Invalid, ask again
	RET			;  else param loaded
;
;	Check if correct response entered
;
CKRSP	LD	(TTYP),HL	;Save type position
;
MVUP	LD	A,0FH		;Low 4 bits for length
	LD	C,(HL)		;Get type byte
	AND	C		;Fetch length
UP	INC	HL		;Bump pointer
	DEC	A		;Less length
	JR	NZ,UP		;Go for length
	INC	HL		;Bump to next
	LD	A,(HL)		;Get response byte
	AND	NUM!FLAG!STR	;Response type bits
	AND	C		;Compare to entered
	RET			;Return with status
;
;	Query on, param not entered, prompt for it
;
GETRSP	PUSH	HL		;Save driver address
	LD	HL,GETRSPR	;Return vector
	EX	(SP),HL		;Leave get display driver
	JP	(HL)		;Display prompt
;
GETRSPR	LD	B,4		;Command get cursor
	@@VDCTL			;Fetch cursor
	LD	L,20		;Column to position to
	LD	B,3		;Command put cursor
	@@VDCTL			;Setup new cursor
	LD	HL,PROMPT	;Prompt text
	CALL	$DSPLY		;Display prompt
	XOR	A		;Load zero
	LD	(FRESP),A	;Clear response byte
;
	LD	HL,INBUF	;Key input buffer
	LD	BC,10<8+0	;Max input length
	@@KEYIN			;Get user input
	JP	C,$ABORT	;Terminate on BREAK
;
;	Evaluate user input
;
	INC	B		;Check if nil input
	DEC	B		;B=0?
	RET	Z		;No input, go
;
	LD	HL,0		;Get param pointer
TTYP	EQU	$-2
	LD	A,(HL)		;Get response type
	AND	0F0H		;  attribute only
	OR	1		;Single byte char
	LD	(FTYP),A	;Pass to new block
;
	LD	HL,FSTR		;Set command pointer
	LD	DE,PTBL2	;Mini-param table
	@@PARAM			;Evaluate input
	RET	NZ		;Invalid, go
;
	LD	HL,(TTYP)	;Get response pointer
	CALL	MVUP		;Move to response byte
	LD	A,(FRESP)	;Get input response
	LD	(HL),A		;  to param block
	INC	HL		;Bump to word pointer
	CALL	GETHL		;Get pointer
	LD	BC,(FPARM)	;Get temp param
	LD	(HL),C		;Load into param block
	INC	HL		;Bump pointer
	LD	(HL),B		;New param loaded
	XOR	A		;Set NO error
	SCF			;Carry = input
	RET			;Done
;
;	Init default settings
;
DEFALT	LD	(IX+MSMASK),DEFMS
	LD	(IX+UCIMAGE),DEFUC
	LD	(IX+BAUDRT),DEFBA
	LD	(IX+BRK),DEFBR
	RET
;
;	Text area
;
	IF	@MOD4
MDNAME	DB	'$CL'
	DB	_ETX
	ENDIF
;
	IF	@MOD2
MDNAME1	DB	'$CL'
	DB	_ETX
MDNAME2	DB	'$CM'
	DB	_ETX
	ENDIF
;
BADDCB	DB	'COM/DVR not installed'
	DB	_CR
;
PROMPT	DB	'? '
	DB	_ETX
;
;	Valid baud rate lookup table
;
BAUDTBL	DW	50,75,110,135,150,300,600,1200,1800
	DW	2000,2400,3600,4800,7200,9600,19200
;
;	Display driver lookup table
;
DSPTBL	DW	DMSG1		;'RS232 params: '
	DW	DMSG2		;'BAUD='
	DW	DMSG23		;', '
	DW	DMSG3		;'WORD='
	DW	DMSG23		;', '
	DW	DMSG4		;'STOP='
	DW	DMSG23		;', '
	DW	DMSG5		;'PARITY='
	DW	DMSG23		;', '
	DW	DMSG6		;'BREAK='
;
	DW	DMSG7		;'output: '
	DW	DMSG8		;'DTR='
	DW	DMSG23		;', '
	DW	DMSG9		;'RTS='
;
	DW	DMSG10		;'input: '
	DW	DMSG11		;'RI='
	DW	DMSG23		;', '
	DW	DMSG12		;'DSR='
	DW	DMSG23		;', '
	DW	DMSG13		;'CD='
	DW	DMSG23		;', '
	DW	DMSG14		;'CTS='
	DW	DMSG22		;_cr
	DW	0		;Terminator
;
;	Parameter pointer table
;
BREAKP	DW	0
QPARM	DW	0
BAUDP	DW	0
WORDP	DW	0
STOPP	DW	0
PARITYP	DW	0
EVENP	DW	0
ODDP	DW	0
DTRP	DW	0
RTSP	DW	0
RIP	DW	0
CDP	DW	0
DSRP	DW	0
CTSP	DW	0
DFPARM	DW	0
PORTD	DW	0
FPARM	DW	0
;
MSG1	DB	0		;Will be LF after 1st DSP
	DB	'RS232'
	IF	@MOD2
MSG1A	DB	'A'
	ENDIF
	DB	' parameters: '
	DB	_ETX
;
MSG2	DB	'Baud='
	DB	_ETX
;
MSG3	DB	'Word='
	DB	_ETX
;
MSG4	DB	'Stop='
	DB	_ETX
;
MSG5	DB	'Parity='
	DB	_ETX
;
MSG6	DB	'Break='
	DB	_ETX
;
MSG7	DB	_LF
	DB	'Output control: '
	DB	_ETX
;
MSG8	DB	'DTR='
	DB	_ETX
;
MSG9	DB	'RTS='
	DB	_ETX
;
MSG10	DB	_LF
	DB	'Input control: '
	DB	_ETX
;
MSG11	DB	'RI='
	DB	_ETX
;
MSG12	DB	'DSR='
	DB	_ETX
;
MSG13	DB	'CD='
	DB	_ETX
;
MSG14	DB	'CTS='
	DB	_ETX
;
MSG15	DB	'ON'
	DB	_ETX
;
MSG16	DB	'OFF'
	DB	_ETX
;
MSG17	DB	'ODD'
	DB	_ETX
;
MSG18	DB	'EVEN'
	DB	_ETX
;
MSG19	DB	'IGNORE'
	DB	_ETX
;
MSG20	DB	'00000'
	DB	_ETX
;
MSG21	DB	'X',_APOS
MSG21A	DB	'00',_APOS
	DB	_ETX
;
MSG22	DB	_CR
;
MSG23	DB	', '
	DB	_ETX
;
;	Parameter evaluation table
;
PRMTBL$	DB	80H		;Extended param
;
BRTYP	DB	5!FLAG!NUM
	DB	'BREAK'
BRRESP	DB	0
	DW	BREAKP
;
	DB	5!ABB!FLAG
	DB	'QUERY'
QRESP	DB	0
	DW	QPARM
;
BTYP	DB	4!ABB!NUM
	DB	'BAUD'
BRESP	DB	0
	DW	BAUDP
;
WTYP	DB	4!ABB!NUM
	DB	'WORD'
WRESP	DB	0
	DW	WORDP
;
STYP	DB	4!ABB!NUM
	DB	'STOP'
SRESP	DB	0
	DW	STOPP
;
PTYP	DB	6!ABB!FLAG!STR
	DB	'PARITY'
PRESP	DB	0
	DW	PARITYP
;
ETYP	DB	4!ABB!FLAG
	DB	'EVEN'
ERESP	DB	0
	DW	EVENP
;
OTYP	DB	3!ABB!FLAG
	DB	'ODD'
ORESP	DB	0
	DW	ODDP
;
DTYP	DB	3!FLAG
	DB	'DTR'
DTRESP	DB	0
	DW	DTRP
;
RTYP	DB	3!FLAG
	DB	'RTS'
RTRESP	DB	0
	DW	RTSP
;
RITYP	DB	2!FLAG
	DB	'RI'
RIRESP	DB	0
	DW	RIP
;
CDTYP	DB	2!FLAG
	DB	'CD'
CDRESP	DB	0
	DW	CDP
;
DSTYP	DB	3!FLAG
	DB	'DSR'
DSRESP	DB	0
	DW	DSRP
;
CTTYP	DB	3!FLAG
	DB	'CTS'
CTRESP	DB	0
	DW	CTSP
;
	DB	7!ABB!FLAG
	DB	'DEFAULT'
	DB	0
	DW	DFPARM
;
	IF	@MOD2
	DB	4!NUM
	DB	'PORT'
PORTP	DB	0
	DW	PORTD
	ENDIF
;
	DB	0		;List terminator
;
;	Evaluate and setup user parameters
;
SETPARAM
	LD	HL,PRMERR	;Param error exit vector
	PUSH	HL		;Leave for quick exits
;
;	Evaluate BAUD
;
SETBAUD	LD	A,(BRESP)	;Get baud response
	OR	A		;Anything?
	JR	Z,SETWORD	;Nope, go
	CALL	CKBAUD		;Get baud setting
	RET	NZ		;Go if error
	LD	(IX+BAUDRT),A	;  else save new baud
;
;	Evaluate WORD
;
SETWORD	LD	C,(IX+UCIMAGE)	;P/u current setings
	LD	A,(WRESP)	;Get word response
	OR	A		;Anything?
	JR	Z,SETSTOP	;Nope, continue
	LD	DE,(WORDP)	;Get parameter
	INC	D		;Check msb
	DEC	D		;D<>0?
	RET	NZ		;>256?
	LD	A,E		;Get lsb
	SUB	5		;Adjust 0 relative
	RET	C		;Go if out of range
	CP	4		;5-8?
	RET	NC		;Out of range
	OR	A		;Clear carry, set PV
	JP	PE,$+5		;Go if 5/8
	XOR	3		;Change 6=>7=>6
	RRCA			;Align to bits 6/5
	RRCA
	RRCA
	LD	B,01100000B	;For bit setup
	CALL	SETBITS		;Setup in C register
;
;	Evaluate STOP
;
SETSTOP	LD	A,(SRESP)	;Get response byte
	OR	A		;Anything?
	JR	Z,SETPAR	;Nope, continue
	LD	DE,(STOPP)	;Get input
	INC	D		;Check for out of range
	DEC	D		;D<>0?
	RET	NZ		;>256
	LD	A,E		;Get lsb
	OR	A		;0?
	RET	Z		;Invalid if not
	CP	3		;1/2?
	RET	NC		;Invalid
	DEC	A		;Change 1|2 to 0|1
	RLCA			;Align result
	RLCA
	RLCA
	RLCA
	LD	B,00010000B	;Init mask
	CALL	SETBITS		;Setup in C register
;
;	Evaluate PARITY
;
SETPAR	LD	A,(PRESP)	;Get parity response
	OR	A		;Any input?
	JR	Z,SETPEO	;Nope, check EVEN|ODD
;
;	Check if response was string or switch
;
	LD	DE,(PARITYP)	;Get user pointer
	BIT	6,A		;Switch?
	JR	NZ,SETPOF	;Yes, set ON/OFF
;
;	Response was string, check 'E'|'O'
;
	LD	A,(DE)		;Get input
	CALL	UCASE		;Make upper case
	CP	'O'		;Odd?
	JR	Z,SETPO		;Yes, go
	CP	'E'		;Even?
	RET	NZ		;Neither, invalid
SETPE	SET	7,C		;Set EVEN parity
	JR	SETPAEO		;Continue
SETPO	RES	7,C		;Set ODD parity
SETPAEO	RES	3,C		;Set ON parity
	JR	SETBRK		;Continue
;
;	Response was switch, check ON|OFF
;
SETPOF	LD	A,D		;Check input
	OR	E		;=0000?
	SET	3,C		;Set OFF
	JR	Z,SETBRK	;Continue if yes
	RES	3,C		;Set ON
;
;	Check for ODD|EVEN params
;
SETPEO	LD	A,(ORESP)	;Get odd response
	OR	A		;Anything?
	JR	Z,SETPAE	;Nope, check EVEN
	LD	DE,(ODDP)	;Get user input
	LD	A,D		;Check for nil
	OR	E		;DE=0000?
	SET	7,C		;ODD=off?
	JR	Z,SETPAE	;Go if yes
	RES	7,C		;ODD=on
;
SETPAE	LD	A,(ERESP)	;Get even response
	OR	A		;Anything?
	JR	Z,SETBRK	;Nope, continue
	LD	DE,(EVENP)	;Get param
	LD	A,D		;Check for nil
	OR	E		;DE=0000?
	RES	7,C		;EVEN=off?
	JR	Z,SETBRK	;Go if yes
	SET	7,C		;EVEN=on
;
;	Evaluate BREAK
;
SETBRK	LD	A,(BRRESP)	;Get user response
	OR	A		;Anything?
	JR	Z,SETDTR	;Nope, continue
	LD	DE,(BREAKP)	;Get user input
	BIT	6,A		;Switch?
	JR	NZ,SETBOF	;Yes, check ON|OFF
;
;	Value entered, check if in range
;
	INC	D		;Check msb
	DEC	D		;D<>0?
	RET	NZ		;>256?
	JR	UPDBRK		;Continue
;
;	Switch entered, check if on/off
;
SETBOF	LD	A,D		;Get input
	OR	E		;DE=0000?
	LD	E,80H		;Default
	JR	Z,UPDBRK	;Go if off
	LD	E,03H		;Default
UPDBRK	LD	(IX+BRK),E	;Update data
;
;	Evaluate DTR
;
SETDTR	LD	A,(DTRESP)	;Get user response byte
	OR	A		;Anything?
	JR	Z,SETRTS	;Continue if not
	LD	DE,(DTRP)	;Get user param
	LD	A,D		;Check if anything
	OR	E		;DE=0000?
	SET	1,C		;Set OFF
	JR	Z,SETRTS	;Go if yes
	RES	1,C		;Set ON
;
;	Evaluate RTS
;
SETRTS	LD	A,(RTRESP)	;Get user response byte
	OR	A		;Anything?
	JR	Z,UPDCI		;Continue if not
	LD	DE,(RTSP)	;Get user param
	LD	A,D		;Check if 0
	OR	E		;DE=0000?
	SET	0,C		;Set OFF
	JR	Z,UPDCI		;Go if yes
	RES	0,C		;Set ON
UPDCI	SET	2,C		;Enable transmit
	LD	(IX+UCIMAGE),C	;Update new data
;
;	Evaluate RI
;
SETRI	LD	HL,RIRESP	;Response byte
	LD	C,00000001B	;Bit to set
	CALL	SETIT		;Setup data
;
;	Evaluate DSR
;
SETDSR	LD	HL,DSRESP	;Response byte
	LD	C,00000100B	;Bit mask
	CALL	SETIT		;Setup data
;
;	Evaluate CD
;
SETCD	LD	HL,CDRESP	;Response byte
	LD	C,00000010B	;Bit mask
	CALL	SETIT		;Setup data
;
;	Evaluate CTS
;
SETCTS	LD	HL,CTRESP	;Response byte
	LD	C,00001000B	;Bit mask
	CALL	SETIT		;Setup data
;
;	Evaluation complete
;
	POP	AF		;Remove param error vect
	RET			;Return from evaluate
;
SETIT	INC	(HL)		;Any response?
	DEC	(HL)		;(HL) = 00?
	RET	Z		;Back if no change
	INC	HL		;Point to response data
	CALL	GETHL		;Load HL with (HL)
	CALL	GETHL		;Get user response
	LD	A,C		;Get response data ON
	RLCA			;Align to upper 4 bits
	RLCA
	RLCA
	RLCA
	OR	C		;Combine
	LD	B,A		;Set response data OFF
	CPL			;Reverse bits
	AND	(IX+MSMASK)	;Drop desired bits
	LD	E,A		;Save new mask
	LD	A,H		;Check if OFF
	OR	L		;HL = 0000?
	LD	A,B		;Get OFF bits
	JR	Z,$+3		;Go if off
	LD	A,C		;Get ON bits
	OR	E		;Combine with remainder
	LD	(IX+MSMASK),A	;Update mask
	RET			;Done
;
;	Set bits in C from A using B as mask
;
SETBITS	AND	B		;Mask others
	PUSH	AF		;Save data
	LD	A,B		;Get mask
	CPL			;Reverse for mask off
	AND	C		;Remove undesired bits
	POP	BC		;B = new bits
	OR	B		;Combine
	LD	C,A		;Update
	RET			;New bits set
;
;	Fetch HL from (HL)
;
GETHL	LD	A,(HL)		;Get lsb
	INC	HL		;Bump pointer
	LD	H,(HL)		;Get msb
	LD	L,A		;HL = (HL)
	RET			;Done
;
;	Convert char in A to upper case
;
UCASE	CP	'a'		;In range?
	RET	C		;Nope, go
	CP	'z'+1		;In range?
	RET	NC		;Nope, go
	AND	5FH		;  else make upper case
	RET			;Done
;
;	Check for valid baud rate entered
;
CKBAUD	LD	DE,(BAUDP)	;Baud parm (default 300)
	LD	HL,BAUDTBL	;Point to baud table
	LD	BC,16<8+0	;B=count, C=position
;
BLOOP	LD	A,(HL)		;Fetch LSB baud
	INC	HL		;Bump table
	CP	E		;Lsb match?
	JR	NZ,NOMATB	;Nope, go next entry
	LD	A,(HL)		;Get MSB baud
	CP	D		;Msb match?
	JR	Z,MATCHB	;Yes, baud found
;
NOMATB	INC	HL		;Bump to next entry
	INC	C		;Bump position count
	DJNZ	BLOOP		;Go for table length
	RET			;Param error
;
MATCHB	LD	A,C		;Pick up baud rate code
	RLCA			;Align to high bits
	RLCA
	RLCA
	RLCA
	OR	C		;Use for xmit and rcv
	CP	A		;Z=good value
	RET			;Return with BAUD setting
;
;	Nil params entered, display current settings
;
SHOW	EQU	$
	IF	@MOD2
	LD	A,-1		;Set NO flag
	LD	(SHOWF),A	;Save flag
	LD	DE,MDNAME1	;CL1
	LD	A,'A'		;Comm A
	LD	(MSG1A),A	;To text
	CALL	SHOW1		;Display
	LD	DE,MDNAME2	;CL2
	LD	A,'B'		;Comm B
	LD	(MSG1A),A	;To text
	CALL	SHOW1		;Display
	LD	A,-1		;Get flag
SHOWF	EQU	$-1
	OR	A		;Any found?
	JP	NZ,BADMOD	;Not installed
	RET			;  else OK
;
SHOW1	@@GTMOD			;Locate module
	RET	NZ		;Module not found
	XOR	A		;Set module found
	LD	(SHOWF),A	;Init flag
	PUSH	DE		;Pass to IX
	POP	IX		;IX => module
	ENDIF
;
	JP	DSPALL		;Display all settings
;
;	Mini param block for 'query' evaluation
;
PTBL2	DB	80H		;Extended param
;
FTYP	DB	FLAG!NUM!1
	DB	'F'
FRESP	DB	0
	DW	FPARM
;
	DB	0
;
;	Text string passed to @PARAM for query eval
;
FSTR	DB	'(F='
INBUF	EQU	$		;Keyboard input buffer
;
	END	BEGIN
