; ROUTINES TO TEST THE FD3712 DRIVE CABINET USING THE SSM-IO4
;    PARALLEL INTERFACE BOARD. WIRING BETWEEN THE IO4 AND THE
;    3712 INVERTS THE BYTE AND SWAPS BITS AROUND AS FOLLOWS:
;   
;   BITS 76543210 CONNECT TO
;   BITS 10325476
;
;  MIKE DOUGLAS, APRIL 2021

	ORG	3C00H
;MON	EQU	40H

; FD3712 COMMANDS (INVERTED AND BIT SWAPPED AS ABOVE)

CSTATUS	EQU	0FFH	;00H
CREAD	EQU	03FH	;03H
CWRITE	EQU	0AFH	;05H
CRDCRC	EQU	02FH	;07H
CSEEK	EQU	09FH	;09H
CCLRERR	EQU	01FH	;0BH
CRESTOR	EQU	08FH	;0DH
CSETTRK	EQU	0BBH	;11H
CDRVSEC	EQU	0B7H	;21H
CWRTBUF	EQU	0B3H	;31H
CRDBUF	EQU	0FEH	;40H
CSHIFT	EQU	0BEH	;41H
CRESET	EQU	0BDH	;81H

; CONTROLLER STATUS BITS (BITS SWAPPED AS ABOVE)

SBUSY	EQU	40H	;01H
SCRCERR	EQU	20H	;08H
SWRTPRT	EQU	04H	;10H
SNOTRDY	EQU	08H	;20H
SRDERRS	EQU	28H	;28H
SWRERRS	EQU	0CH	;30H

; INTERFACE BOARD 

CMDOUT	EQU	0C0H
DATAIN	EQU	0C0H
DATAOUT	EQU	0C1H

; DRIVE EQUATES 

SECLEN	EQU	128

; CONSOLE I/O

SIOCSR	EQU	10H
SIODR	EQU	11H
RCVRDY	EQU	01H
XMTRDY	EQU	02H

; MISC

CR	EQU	0DH
LF	EQU	0AH
LFEOL	EQU	8AH		;LF AT END OF LINE
SPEOL	EQU	0A0H		;SPACE AT END OF LINE

; START OF CODE

START:	LXI	SP,STACK
	MVI	A,CRESET	;RESET 3712
	CALL	DOCMD
	

MAINLP:	CALL	DSPMSG		;GET DRIVE
	DB	CR,LF,LF,"Drive:",SPEOL
	CALL	GETCHR
	CALL	DSPCHR
	SUI	"0"
	CPI	4		;VERIFY 0-3
	JNC	MON
	STA	DRVNUM

	CALL	DSPMSG		;GET TRACK
	DB	CR,LF,"Track:",SPEOL
	CALL	GETCHR
	CALL	DSPCHR
	SUI	"0"
	CPI	10		;VERIFY 0-9
	JNC	MON
	STA	TRKNUM

	CALL	DSPMSG		;GET SECTOR
	DB	CR,LF,"Sector:",SPEOL
	CALL	GETCHR
	CALL	DSPCHR
	SUI	"1"
	CPI	9		;VERIFY "1"-"9"
	JNC	MON
	INR	A		;MAKE 1-9
	STA	SECNUM

	CALL	DSPMSG		;GET READ/WRITE
	DB	CR,LF,"Read or Write:",SPEOL
	CALL	GETCHR
	CALL	DSPCHR
	ORI	20H		;UPPER TO LOWER
	CPI	"w"
	JNZ	RDSEC

; FILL AND WRITE THE SECTOR

	LXI	H,OUTBUF
	SHLD	DMADDR
	
	LDA	DRVNUM		;PUT ASCII DRIVE, TRK, SEC
	ADI	30H		;  IN 1ST 3 BYTES
	MOV	M,A
	INX	H
	
	LDA	TRKNUM
	ADI	30H
	MOV	M,A
	INX	H
	
	LDA	SECNUM
	ADI	30H
	MOV	M,A
	INX	H
	
	MVI	B,125		;SECLEN-3
	MVI	A,20H		;START WITH SPACE

WSLOOP:	MOV	M,A
	INR	A
	CPI	7FH
	JNZ	NEXTB
	MVI	A,20H
NEXTB:	INX	H
	DCR	B
	JNZ	WSLOOP

	CALL	WRITE
	JMP	MAINLP
	
; READ THE SECTOR AND DISPLAY

RDSEC:	CALL	DSPMSG
	DB	CR,LF,LF,"Data Read:",CR,LFEOL

	LXI	H,INBUF
	SHLD	DMADDR
	CALL	READ
	LHLD	DMADDR
	MVI	B,SECLEN

RSLOOP:	MOV	A,M
	CALL	DSPCHR
	INX	H
	DCR	B
	JNZ	RSLOOP
	
	JMP	MAINLP

; DISPLAY MESSAGE

DSPMSG:	POP	H

DMLOOP:	MOV	A,M
	CALL	DSPCHR
	XRA	M		;MSBIT TERMINATOR?
	INX	H
	JZ	DMLOOP		;NO

	PCHL			;RETURN

; DISPLAY CHARACTER

DSPCHR:	MOV	C,A

DCLOOP:	IN	SIOCSR
	ANI	XMTRDY
	JZ	DCLOOP

	MOV	A,C
	ANI	7FH
	OUT	SIODR
	RET

; GET CHARACTER

GETCHR:	IN	SIOCSR
	ANI	RCVRDY
	JZ	GETCHR

	IN	SIODR		;A=NEW CHARACTER
	ANI	7FH
	RET

; READ - READ SECTOR 

READ:	CALL	SEEK
	MVI	C,10		;C=RETRY COUNTER

RDRTRY:	MVI	A,CREAD
	CALL	DOCMD
	ANI	SRDERRS
	JZ	RDXFER		;GOOD READ, GO TRANSFER DATA
	
	CALL	CLRERR
	DCR	C
	JNZ	RDRTRY
	JMP	MON		;FAILED

RDXFER:	LHLD	DMADDR
	MVI	C,SECLEN

RDLOOP:	MVI	A,CRDBUF	;ENABLE FIFO BUFFER OUTPUT
	OUT	CMDOUT
	IN	DATAIN
	MOV	M,A
	MVI	A,CSHIFT	;SHIFT FIFO TO NEXT BYTE
	OUT	CMDOUT
	INX	H 
	DCR	C
	JNZ	RDLOOP

	MVI	A,CSTATUS	;LEAVE CONTROLLER IN STATUS STATE
	OUT	CMDOUT
	RET

; WRITE - WRITE SECTOR

WRITE:	CALL	SEEK 
	LHLD	DMADDR
	MVI	C,SECLEN 

WRLOOP:	MOV	A,M		;A=NEXT BYTE TO WRITE
	OUT	DATAOUT
	MVI	A,CWRTBUF	;COMMAND TO MOVE BYTE TO WRITE BUFFER
	OUT	CMDOUT	
	MVI	A,CSTATUS	;RETURN BIT ZERO TO ZERO
	OUT	CMDOUT
	INX	H 
	DCR	C
	JNZ	WRLOOP

	MVI	A,CWRITE 
	CALL	DOCMD
	ANI	SWRERRS
	RZ			;NO ERROR, EXIT
	CALL	CLRERR 		;ELSE, FAILED
	JMP	MON

; SEEK - SEEK TO TRACK AND SPECIFY SECTOR

SEEK:	CALL	SELSEC		;SELECT DRIVE, SET SECTOR
	MVI	E,2		;C=RETRY COUNTER

SKRTRY:	LDA	TRKNUM		;SET TRACK
	CALL	SETTRK
	MVI	A,CSEEK		;DO THE SEEK
	CALL	DOCMD
	ANI	SRDERRS	
	RZ			;GOOD SEEK
	
	CALL	CLRERR		 
	DCR	E 
	JNZ	SKRTRY
	JMP	MON		;GIVE UP

SELSEC:	LDA	DRVNUM
	ANI	03H
	RRC			;DRIVE NUMBER IN UPPER TWO BITS
	RRC
	MOV	C,A
	
	LDA	SECNUM		;COMBINE DRIVE WITH SECTOR NUMBER
	ORA	C
	JMP	SETSEC		;SET SECTOR AND EXIT

; CLRERR - CLEAR CONTROLLER ERRORS

CLRERR:	MVI	A,CCLRERR	;CLEAR CONTROLLER ERRORS
	JMP	DOCMD

; SETTRK - SET TRACK IN CONTROLLER

SETTRK:	MVI	C,CSETTRK
	JMP	CMDDAT
	
; SETSEC - SET DRV/SECTOR IN CONTROLLER

SETSEC:	MVI	C,CDRVSEC	;SET DRIVE/SECTOR, FALL INTO CMDDAT

CMDDAT:	PUSH	PSW		;MAP BITS 76543210 TO 10325476
	RLC
	RLC
	ANI	33H		;--32--76
	MOV	B,A		;B=half result

	POP	PSW		
	RRC
	RRC
	ANI	0CCH		;10--54--
	
	ADD	B		;A=ALL BITS SWAPPED
	CMA			;INVERT BYTE
	OUT	DATAOUT		;SET DATA
	MOV	A,C		;A=COMMAND TO WRITE

; DOCMD - ISSUE COMMAND FROM A, WAIT FOR COMPLETION

DOCMD:	OUT	CMDOUT 
	MVI	A,CSTATUS	;EXIT IN EXAMINE STATUS
	OUT	CMDOUT

WTCMD:	IN	DATAIN		;WAIT FOR NOT BUSY
	ANI	SBUSY
	JZ	WTCMD		;DATA COMES IN INVERTED

	IN	DATAIN		;GET STATUS
	CMA			;DATA COMES IN INVERTED
	RET

; DATA
	
INBUF:	DS	SECLEN
OUTBUF:	DS	SECLEN
DRVNUM:	DS	1
TRKNUM:	DS	1
SECNUM:	DS	1
DMADDR:	DS	2
CHAR:	DS	1
	DS	32
STACK:	DS	1		;EQU $ FAILS HERE

	END
	EOA
