;*******************************************************************
;
; DSTEP - Disk test utility
;    Using only the Altair front panel switches, this utility
;    allows selection of a particular drive number, seeking to
;    a specified track, and loading/unloading the head. These
;    features are useful, for example, when aligning a drive
;    using an alignment disk.
;
;    PROM Origin: FC00
;
;    This PROM is part of the test suite used by MITS bench 
;    technician Robert Lopez. These PROMs were used at MITS
;    to test and debug boards for the Altair 8800 computer.
;
;    OPERATION:
;
;    1) Examine the PROM address (FC00h). Do NOT depress RUN.
;
;    2) Set the desired drive number on the sense switches and
;       then depress RUN.
;
;    Sense switch A15 loads and unloads the head. Switch up
;    raises the head, switch down lowers the head.
;
;    The remaining sense switches specify a track number to
;    which the drive will immediately seek. Typically used
;    track numbers for disk alignment are:
;
;	 0 (00h) - Data amplitude
;        1 (01h) - Index alignment
;	38 (26h) - Radial alignment
;       76 (4Ch) - Index alignment
;
;    NOTE: Even though this PROM is at a typical address in
;          the Turnkey module, if the Turnkey is Rev 1 or has
;	   the 88-CLG mod (disables PROM upon IN from the sense
;	   switches), this PROM will not work in these boards
;          as it would disable itself immediately upon reading
;	   the sense switches the first time.
;
;    Disassembled 1/23/2016 by Mike Douglas from a 1702a PROM
;    provided by Tom Sanderson.
;
;*******************************************************************

; I/O port addresses

SENSESW	equ	0FFH		;front panel sense switch address
DRVSEL	equ	8		;drive select port (out)
DRVSTAT	equ	8		;drive status port (in)
DRVCTL	equ	9		;drive control port (out)

; FDC status bit masks

HEADMSK	equ	004h		;mask to get head load bit alone
MOVEMSK	equ	002h		;mask to get MVHEAD bit alone
TRK0MSK	equ	040h		;mask to get TRACK0 bit alone

; FDC command bit masks

STEPIN	equ	001h		;drive command - step in
STEPOUT	equ	002h		;drive command - step out
HLOAD	equ	004h		;drive command - load head (8")
HUNLOAD	equ	008h		;drive command - unload head

; Misc equates

NUMTRK	equ	77		;number of tracks

	org	0FC00h
;----------------------------------------------------------------------
;  On initial entry, select the drive specified on the lower four
;  sense switches, then restore to track zero.
;----------------------------------------------------------------------
	in	SENSESW		;drive number from sense switches
	ani	0Fh		
	mov	d,a		;d=drive number

; select drive

select:	mov	a,d		;output drive number to select register
	out	DRVSEL
	in	DRVSTAT		;see if select worked
	inr	a		;test for 0FFh (not selected)
	jz	select

; restore to track zero

seek0:	in	DRVSTAT		;wait until OK to move the head
	ani	MOVEMSK
	jnz	seek0

	mvi	a,STEPOUT	;issue step out
	out	DRVCTL

	in	DRVSTAT		;reached track zero?
	ani	TRK0MSK
	jnz	seek0		;no, do another step out

	mvi	b,0		;b=current track number

;----------------------------------------------------------------------
;  Once the drive is selected and restored to track zero, loop here
;  stepping to the track specified on the sense switches. Head is
;  raised/lowered with A15
;----------------------------------------------------------------------

; Do head load/unload based on A15 (1=unload, 0=load)

hdCmd:	in	SENSESW		;head load/unload based on A15

	rlc			;move MSbit into LSbit
	ora	a		;clear carry
	rar			;original MSbit is now in carry
	mov	c,a		;c=original value with MSbit clear

	mvi	a,HLOAD		;head load if MS switch (A15) is off
	jnc	doHead
	mvi	a,HUNLOAD	;head unload if MS switch (A15) is on

doHead:	out	DRVCTL		;issue head load or unload

; Step in/out to track specified on front panel

wtMove:	in	DRVSTAT		;wait for OK to move head
	inr	a		;test for lost drive select (FF)
	jz	select		;select lost, re-select same drive num

	dcr	a		;restore the status just read
	ani	MOVEMSK		;OK to move head?
	jnz	wtMove		;no, keep waiting	

	mov	a,c		;a=sense switches with MS bit cleared
	cpi	NUMTRK		;sense switches >= Num tracks? (invalid)
	jnc	hdCmd		;invalid # of tracks, don't step

	cmp	b		;reach track set on sense switches?
	jz	hdCmd		;yes, start loop over

	jc	stpOut		;if requested < current, step out

	mvi	a,STEPIN	;otherwise, issue step in
	out	DRVCTL
	inr	b		;increment track number
	jmp	wtMove

stpOut:	mvi	a,STEPOUT	;issue step out
	out	DRVCTL
	dcr	b		;decrement track number
	jmp	wtMove
	
	end
