$TITLE('GPIB SERVICE') DEBUG PAGEWIDTH(80)
;
;*****************************************************
;THIS ROUTINE IS ENTERED BY THE EXECUTIVE MODULE UPON
;SUCCESSFUL PROCESSING OF THE GPIB INTERRUPT.  IT
;IS ALSO ENTERED FOR THE PURPOSE OF RESETTING THE GPIB
;TO A POWER ON CONDITION OR TO ENABLE A DATA TRANSFER
;WHEN THE TALKER ACTIVE STATE IS DETECTED.
;*****************************************************
;
	NAME	GPIB4
	PUBLIC	GPIBSR,GPIBR,STAT1,TALK,RSTAT,SSTAT
	PUBLIC	STAT2,BFPTR,BTCNT,RTN1,TRENS,NBAFG
	EXTRN	TST2ND,EOLCH
;	DATE	16 SEP 80
;
	CSEG
;
GPIBSR:
;
;TEST FOR LISTEN INTERRUPT
;
	MOV	C,A		;SAVE INTR. STATUS
	LDA	STAT1		;TEST LACS
	RRC
	JC	LISTEN		;LISTEN ROUTINE
;
;TEST INTERRUPT STATUS
;
	MOV	A,C		;RETURN STATUS
	RRC			;TEST FOR MTA
	JC	SMTA		;SET MTA
	RRC			;TEST FOR OTA
	JC	RMTA		;RESET MTA
	RRC			;TEST FOR MLA
	JC	SMLA		;SET MLA
	RRC			;TEST FOR ATN
	JNC	SLACS		;SET LACS
;
;TEST UNIVERSAL COMMAND GROUP
;
TUCG:
	IN	GPIB		;INPUT COMMAND
	ANI	CMASK		;MASK MSB
	CPI	UNL		;TEST FOR UNL
	JZ	RLADS		;RESET LADS
	CPI	SPE		;TEST FOR SPE
	JZ	SSPMS		;SET SPMS
	CPI	SPD		;TEST SPD
	JZ	RSPMS		;RESET SPMS
	CPI	DCL		;TEST FOR DCL
	JZ	RESET		;RESET GPIB
;
;TEST FOR SECONDARY ADDRESS
;
	MOV	C,A		;SAVE COMMAND
	LDA	STAT1		;FETCH STATUS
	ANI	LADSM OR TADSM	;ADDRESSED?
	JZ	RTN1		;NO-RETURN
	MOV	B,A		;SAVE STATUS
	MOV	A,C		;GET COMMAND
	ANI	60H		;SECONDARY ADDR?
	CPI	60H
	JZ	TST2ND		;YES-BRANCH
;
;TEST ADDRESSED COMMAND GROUP
;
TACG:
	MOV	A,B		;GET STATUS
	ANI	LADSM		;ADDR. TO LISTEN?
	JZ	RTN1		;NO-RETURN
	MOV	A,C
	CPI	SDC		;TEST FOR SDC
	JZ	RESET
	CPI	GTL		;TEST FOR GTL
	JZ	RREMS		;RESET REMS
;
;RETURN IF TEST FAILS
;
RTN1:
	LDA	STAT2		;FETCH OUTPUT STATUS
	ORI	RINTM		;RESET INTR.
	OUT	GPIBST
RTN2:
	POP	H		;RESTORE REGISTERS
	POP	D
	POP	B
	POP	PSW
	EI			;ENABLE INTR.
	RET
;
;SET MY TALK ADDRESS
;
SMTA:
	MVI	B,TADSM		;SET TADS
	CALL	SSTAT
	MVI	B,LADSM		;RESET LADS
	CALL	RSTAT
	LDA	STAT2		;FETCH OUTPUT STATUS
	ANI	NOT LADRM	;RESET LADR
	ORI	TADRM		;SET TADR
	STA	STAT2
	STA	NBAFG		;SET NBA FLAG
	ORI	RINTM		;RESET INTR.
	OUT	GPIBST
	LDA	STAT1		;TEST SPMS
	ANI	SPMSM
	JNZ	SPOLL		;SERIAL POLL ROUTINE
	JMP	RTN2
;
;RESET MY TALK ADDRESSS
;
RMTA:
	MVI	B,TADSM		;RESET TADS
	CALL	RSTAT
	LDA	STAT2		;RESET TADR
	ANI	NOT TADRM	
	STA	STAT2
	JMP	RTN1
;
;SET MY LISTEN ADDRESS
;
SMLA:
	MVI	B,LADSM		;SET LADS
	CALL	SSTAT
	MVI	B,TADSM		;RESET TADS
	CALL	RSTAT
	MOV	B,A		;SAVE NEW STATUS
	LDA	STAT2
	ANI	NOT TADRM	;RESET TADR
	ORI	LADRM		;SET LADR
	STA	STAT2
	OUT	GPIBST
;
;TEST REMOTE STATUS
;
REMST:
	MOV	A,B
	RLC
	RLC
	RLC
	JC	RTN1		;REMS SET-RTN
	RLC			;REN TO CARRY
	JNC	RTN1		;REN NOT SET-RTN
	MOV	A,B		;SET REMS
	ORI	REMSM
	STA	STAT1		;RESTORE STATUS
	JMP	RTN1
;
;SET LISTENER ACTIVE STATE
;
SLACS:
	LDA	STAT1		;TEST LADS
	ANI	LADSM
	JZ	RTN1		;RETURN IF NOT SET
	MVI	B,LACSM
	CALL	SSTAT
	JMP	LISTEN		;LISTEN ROUTINE
;
;RESET LISTENER ADDRESSED STATE
;
RLADS:
	MVI	B,LADSM OR LACSM
	CALL	RSTAT		;RESET STATUS
	LDA	STAT2		;RESET LADR
	ANI	NOT LADRM
	STA	STAT2
	OUT	GPIBST
	JMP	RTN1
;
;SET SERIAL POLL MODE STATE
;
SSPMS:
	MVI	B,SPMSM
	CALL	SSTAT
	JMP	RTN1
;
;RESET SERIAL POLL MODE STATE
;
RSPMS:
	MVI	B,SPMSM OR RSVSM
	CALL	RSTAT
	JMP	RTN1
;
;RESET GPIB
;
RESET:
	CALL	GPIBR
	JMP	RTN1
;
;RESET REMOTE STATE
;
RREMS:
	MVI	B,REMSM
	CALL	RSTAT
	JMP	RTN1
;
;SET STATUS SUBROUTINE
;
SSTAT:
	LDA	STAT1		;FETCH STATUS
	ORA	B		;SET STATUS
	STA	STAT1		;STORE STATUS
	RET
;
;RESET STATUS SUBROUTINE
;
RSTAT:
	LDA	STAT1
	CMA
	ORA	B		;RESET STATUS
	CMA
	STA	STAT1
	RET
;
;************************
;
;GPIB SERIAL POLL ROUTINE
;
;*************************
;
;THE SERIAL POLL ROUTINE IS A SPECIAL TALK ROUTINE
;WHICH WILL OUTPUT DEVICE STATUS OVER THE GPIB
;WHENEVER SPAS IS DETECTED.  THE SERIAL POLL
;IS NORMALLY ACTIVATEDBY THE BUS CONTROLLER IN
;RESPONSE TO A SERVICE REQUEST (SRQ) INTERRUPT
;BY ONE OF THE DEVICES ON THE BUS.  AS EACH DEVICE
;IS POLLED BIT 6 (DIO7) IS SENT TRUE IF IT IS
;THE DEVICE REQUESTING SERVICE, OTHERWISE IT IS SENT 
;FALSE.
;
SPOLL:
;
;TEST RSV FLIP FLOP
;
	LDA	STAT2		;FETCH OUTPUT STATUS
	MOV	B,A		;SAVE IN B
	ANI	RSVM		;MASK FOR RSV
	JZ	SENDST
;
;RESET RSV FLIP FLOP
;
	MOV	A,B		;RESTORE STATUS
	ANI	NOT RSVM	;RESET SRQ
	STA	STAT2
	OUT	GPIBST
	MVI	A,40H		;RESET RDY F/F
	OUT	XSTAT
	MVI	B,RSVSM		;SET REQ. SER. STAT
	CALL	SSTAT
;
;SEND GPIB STATUS
;
SENDST:
	IN	GPIBST		;WAIT FOR ATN/
	ANI	ATNM
	JNZ	SENDST
	MVI	B,TACSM		;SET TACS
	CALL	SSTAT
	OUT	GPIB
SPWAIT:
	IN	GPIBST		;WAIT FOR ACK
	RLC
	JNC	SPWAIT
	CALL	RSTAT		;RESET TACS
	XRA	A		;CLEAR NBA FLAG
	STA	NBAFG
	LDA	SPEFG		;TEST ENTRY POINT
	ORA	A		;FROM TALK ROUTINE?
	JZ	RTN2		;NO-NORMAL RETURN
	XRA	A		;RESET FLAG
	STA	SPEFG
	RET			;RETURN TO EXEC.
;
;*****************
;
;GPIB TALK ROUTINE
;
;*****************
;
;THE GPIB TALK SUBROUTINE IS CALLED BY THE EXECUTIVE
;PROGRAM TO ENABLE A TRANSFER OF DATA OVER THE 
;GPIB FROM THIS TALKER TO LISTENERS ON THE BUS.  THIS
;SUBROUTINE FINDS THE BUFFER POINTER IN THE HL REGISTER
;AND THE NUMBER OF BYTES IN THE C REG. IF A CARRIARE
;RETURN IS ENCOUTERED BEFORE THE LAST BYTE IS COUNTED
;THE TRANSMISSION IS TERMINATED.
;
TALK:
	LDA	STAT1		;FETCH STATUS
	RLC			;TEST FOR SPMS
	JNC	TALK1		;AHEAD
	STA	SPEFG		;SET FLAG
	JMP	SPOLL		;SERIAL POLL ROUTINE
TALK1:
	LDA	STAT1		;SET TACS
	ORI	TACSM
	STA	STAT1
TALK2:
	MOV	A,M		;FETCH BYTE
	XCHG			;SAVE POINTER
	LXI	H,EOLCH		;POINT AT EOL CHAR.
	CMP	M		;BYTE=EOL?
	JZ	SEOI		;YES-SET EOI
	XCHG			;ELSE-RESTORE PTR.
	DCR	C		;DONE?
	JZ	SEOI		;YES-AHEAD
	OUT	GPIB
TWAIT2:
	IN	GPIBST		;WAIT FOR ACK
	RLC
	JNC	TWAIT2
	INX	H		;ADJUST PTRS,
	JMP	TALK2
SEOI:
	LDA	STAT2		;SET END
	MOV	B,A		;SAVE OUTPUT STATUS
	ORI	ENDMS
	OUT	GPIBST
	MOV	A,M		;SEND LAST BYTE
	OUT	GPIB
TWAIT3:
	IN	GPIBST
	RLC
	JNC	TWAIT3
	MOV	A,B
	OUT	GPIBST
	MVI	B,TACSM		;RESET TACS
	CALL	RSTAT
	XRA	A		;CLEAR NBA FLAG
	STA	NBAFG
	RET
;
;*******************
;
;GPIB LISTEN ROUTINE
;
;*******************
;
;LISTEN AND STORE DATA
;
LISTEN:
	LDA	STAT2		;RESET INT.
	ORI	RINTM
	OUT	GPIBST
	IN	GPIB		;INPUT DATA
	MOV	B,A		;SAVE IN B
	LHLD	BFPTR		;LOAD POINTER
	LDA	BTCNT		;LOAD COUNT
	ORA	A		;TEST COUNT
	JZ	RLACS		;ABORT IF ZERO
	MOV	M,B		;STORE DATA
	INX	H		;INCR. POINTER
	DCR	A		;DECR COUNT
	JZ	RLACS		
	SHLD	BFPTR
	STA	BTCNT
	MOV	A,B		;TEST IF EOL CHAR.
	CPI	CR
	JZ	RLACS
	MOV	A,C
	RLC
	ANI	EOIM
	JNZ	RTN2
RLACS:
	STA	BTCNT		;CLEAR COUNT
	MVI	B,LACSM
	CALL	RSTAT
	JMP	RTN2
;
;
;**************************
;
;GENERAL SYSTEM SUBROUTINES
;
;**************************
;
;RESET TO POWER ON STATE
;
GPIBR:
	XRA	A		;CLEAR ACC.
	STA	STAT1		;CLEAR STATUS
	STA	STAT2		;RESET OUTPUT STATUS
	STA	SPEFG		;RESET SPE FLAG
	STA	BTCNT		;RESET BYTE COUNT
	STC			;RESET INTR. F/F
	RAR
	OUT	GPIBST
	RET
;
;TEST REMOTE ENABLE STATUS - MAY BE CALLED BY THE
;EXECUTIVE ROUTINE TO TEST THE STATUS OF THE REMOTE
;ENABLE LINE. IF DETECTED AS TRUE, THE STATUS BIT
;RENS WILL BE SET UNLESS ALREADY SET. RENS MUST BE
;SET SET IN ORDER TO ENTER THE REMOTE STATE VIA
;REMST: ABOVE. IF DETECTED AS BEING FALSE, RENS AND
;REMS WILL BE RESET.
;
TRENS:
	IN	GPIBST		;STATUS PORT
	ANI	40H		;TEST REN
	LDA	STAT1		;FETCH STATUS
	MVI	B,10H		;TEST RENS
	JNZ	SRENS		;AHEAD IF REN SET
	ANA	B
	RZ			;RTN. IF RENS NOT SET
	MVI	B,30H		;RESET RENS & REMS
	CALL	RSTAT
	RET
SRENS:
	CALL	SSTAT		;SET RENS
	RET
;
;
;**************
;
;MODULE EQUATES
;
;**************
;
;STATUS BYTE MASKS
;
LACSM	EQU	00000001B	;LISTENER ACTIVE
TACSM	EQU	00000010B	;TALKER ACTIVE
TADSM	EQU	00000100B	;TALKER ADDRESSED
LADSM	EQU	00001000B	;LISTENER ADDRESSED
RENSM	EQU	00010000B	;REMOTE ENABLE
REMSM	EQU	00100000B	;REMOTE STATE
RSVSM	EQU	01000000B	;REQUEST SERVICE
SPMSM	EQU	10000000B	;SERIAL POLL MODE
;
;INPUT STATUS PORT MASKS
;
INTM	EQU	00000001B	;INTERRUPT MASK
MTAM	EQU	00000010B	;MTA MASK
OTAM	EQU	00000100B	;OTA INTR. MASK
MLAM	EQU	00001000B	;MLA INTR. MASK
ATNM	EQU	00010000B	;ATN MASK
EOIM	EQU	00100000B	;EOI MASK
RENM	EQU	01000000B	;REN MASK
ACKM	EQU	10000000B	;ACKNOWLEDGE MASK
;
;OUTPUT STATUS MASKS
;
TADRM	EQU	00000001B	;TADR MASK
LADRM	EQU	00000010B	;LADR MASK
ENDMS	EQU	00000100B	;END MASK
RSVM	EQU	00001000B	;RSV MASK
RINTM	EQU	10000000B	;RESET INTR. MASK
;
;GPIB COMMANDS
;
CMASK	EQU	01111111B	;MSB MASK
UNL	EQU	3FH		;UNLISTEN
DCL	EQU	14H		;DEVICE CLEAR
SDC	EQU	04H		;SEL. DEVICE CLEAR
GTL	EQU	01H		;GO LOCAL
SPE	EQU	18H		;SERIAL POLL ENABLE
SPD	EQU	19H		;SERIAL POLL DISABLE
;
;CONTSANTS
;
CR	EQU	0DH		;EOL CRARACTER
;
;I/O PORT ADDRESSES
;
GPIB	EQU	3EH		;GPIB DATA PORT
GPIBST	EQU	3FH		;GPIB STATUS PORT
XSTAT	EQU	30H		;CURSOR STATUS PORT
;
;********************
;
;GPIB RESERVED MEMORY
;
;********************
;
DSEG
;
STAT1:	DS	1		;GPIB STATUS BYTE
STAT2:	DS	1		;OUTPUT STATUS BYTE
BFPTR:	DS	2		;LISTEN BUFFER PTR.
BTCNT:	DS	1		;LISTEN BYTE COUNT
SPEFG:	DS	1		;SERIAL POLL FLAG
NBAFG:	DS	1		;NEW BYTE FLAG
;
	END
