[net.sources] DDD11 sources

ignatz@ihuxx.UUCP (Dave Ihnat, Chicago, IL) (12/30/83)

As usual, delete all lines up to and including the line of dashes, and
execute the remainder as a shellscript.  Good luck!
				Dave Ihnat
				ihuxx!ignatz
------------------------------------------------------------
echo x - dddread.me
cat >dddread.me <<'!E!O!F!'
*******************************************************************************
*******************************************************************************


        DDD Version 1.1     With this program and Dysan Corporation's
                                 "Digital Diagnostic Diskette"tm
                            ($30 for SS and $40 for DS as of 1983...)     
                            
                            You can comprehensively test, verify, and
align the heads of your flexible diskette drive, under your own oper-
ating conditions, without need for expensive oscilloscopes and drive
exercisers, to practically the same precision achievable by the usual
analog methods. Any time you suspect a bug in one of your drives, you
can determine which drive is at fault and what the problem is.
No more expensive shot-in-the-dark trips to the service center; no
more intermittent bugs which won't appear for the serviceman. Takes
the mystery out of flexible diskette systems!!


*******************************************************************************
*******************************************************************************



 
System Requirements:
The DDDtm is available for all flexible diskette formats, and works
independently of any operating system.  This program is built around
CP/M and the 1793 floppy disk controller chip, and can be easily 
configured and assembled (with ASM - no macros... ) for most CP/M
systems. The screen displays require an addressable cursor and clear
screen facility from your terminal, but you could display the 
test results without the trick graphics if you don't have these
capabilities. 


Operator Requirements:
You will have to know how to edit and assemble 8080 assembly 
language. Step-by-step instructions for customizing the program
will be published in Dr. Dobb's Journal, probably in November
1983. The code is well-commented and could probably be customized
without the magazine if you must. You will, however, need to know 
some hardware-specific information about your terminal and disk
controller; count on needing the manufacturers' manuals and/or
cribbing the information from your BIOS source. (The disk reads
must bypass CP/M function calls entirely - you have to send raw
commands to the controller, and retrieve the data byte-by-byte.)


Tests Performed:
Radial Alignment - on six different tracks, to within 1/2 milliinch
Positioner Hysteresis -     "   , using any offset up to full width
Head Azimuth - from -42 to +42 minutes
Index Timing - inner and outer tracks
Diskette Centering - three levels of difficulty (tests bearings, clamping)
Spindle Speed - (not a function of the DDD... )
(Many other problems, such as dirty heads, will show themselves during
these tests...  You will want to get familiar with the results of the
different tests while your drives are working, so that you can recognize
the changes caused by new bugs.)


Verification:
DDD11.ASM is a 47K file
CRC (Version 5.0 and previous...)     6E 94
CRC (Version 5.1 and derivatives...)   7B79

(Comment by Dave Ihnat:  UNIX sum: 49686 <x>, where <x> is 45 on a 1K
 System V filesystem, and (I suspect) 91 on a 512-byte filesystem.  Note
 that the CRC sums most likely *won't* come out correctly. - DMI)


Author:         LOREN AMELANG

CIS Email [70110,551]  (I access Snail Mail more often than Email...
                            but if you want to send machine code...)
Box 24, Philo, CA  95466 0024   (Best way to contact me...)


*******************************************************************************
           Take the mystery out of YOUR flexible disk system !!!
*******************************************************************************
!E!O!F!
echo x - ddd11.asm
cat >ddd11.asm <<'!E!O!F!'
;<><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
;<>******************************************************<>
;<>* 		 					*<>
;<>*	   	          D D D              		*<>
;<>*							*<>
;<>*	            Dysan Corporation       		*<>
;<>*	      Customer Engineering Division		*<>
;<>*	          1244  Reamwood  Avenue		*<>
;<>*		 Sunnyvale, Cal.    94086		*<>
;<>*							*<>
;<>******************************************************<>
;<><><><><><><><><><><><><><><><><><><><><><><><><><><><><> 



;	This document contains information developed by
;	Dysan Corporation (Dysan) and is furnished for 
;	information only.

;	Dysan makes no warranty or representation (expressed
;	or implied) with respect to the accuracy, completeness
;	or usefulness of the information contained herein.
;	Further Dysan assumes no responsibility for liability
;	or damage of any kind which may result from the use 
;	of the information contained herein.

;	THIS PROGRAM IS IN THE PUBLIC DOMAIN, AND MAY BE
;			FREELY COPIED AND DISTRIBUTED
;
;



;	****************************************************************
;
;	USAGE:
;
;	To use this program, a digital alignment disk is required.
;	You may purchase the required "Digital Diagnostic Diskette" (tm)
;	directly from Dysan Corporation.  Available DDD(tm) models are:
;
;	SIDES:............SINGLE SIDED.............DOUBLE SIDED
;	DENSITY:......SINGLE(FM) DOUBLE(MFM)...SINGLE(FM) DOUBLE(MFM)
;	SIZE & TPI:
;	8"     48 TPI   808-100   808-200        808-300   808-400
;	5.25"  48 TPI   508-100   508-200        508-300   508-400
;	5.25"  96 TPI   506-100   506-200        506-300   506-400
;	5.25" 100 TPI   CALL FOR AVAILABILITY    CALL FOR AVAILABILITY
;
;
;	PRICES:	 Single Sided - $30.00     Double Sided - $40.00
;		 Plus appropriate sales taxes and shipping costs
;		 Prices and models subject to change without notice
;
;
;	ORDERING:  Contact your local Dysan sales Rep. or call
;		   Inside Northern California:  (408) 988-3472
;		   Outside Northern California: (800) 551-9000
;
;
;	TECHNICAL INFORMATION:  For information regarding DDD(tm)
;				applications contact Dysan's
;				CE Division TECH-LINE: (408)734-1624
;
;



;	****************************************************************
;
;	HISTORY:
;
;	VERSION 1.0: Developed by Dysan for their Single Card Computer
;					and Hazeltine 1500 terminal
;
;	VERSION 1.1: Modified by Loren Amelang, Box 24, Philo, Ca.
;						  95466 0024
;		Added drive selection; commented out code which required
;		a macro assembler (you can now use ASM); substituted 
;		CP/M BDOS calls for version 1.0 BIOS calls; modified cline
;		& its usage for terminals without clear-to-end-of-line;
;		added display of last sectors read; modified disc
;		read routines for CCS 2422 controller and
;		programmed I/O transfer; 
;
;



;	****************************************************************
;
;	ENVIRONMENT:
;	
;	Digital Research's  MAC  macro assembler has
;	been  used to compile this program.
;
;		    Digitial Research
;	              P.O. Box 579
;		  801 Lighthouse Avenue
;		  Pacific Grove, Ca 93950
;		     (408) 649-3896
;
;	This example skeleton program may be used to read
;	the Digital Diagnostic Diskette. Many features can
;	be added to make a more substantial program. The
;	read routines are directed at the 8 inch "DDD",but
;	can be altered for 5 1/4 inch "DDD"
;		
;	The Western Digital 1793 floppy controller has been
;	chosen because of its wide use in micro computers.
;	This program dosn't depend upon this controller, but
;	the controller used must be able to read FM or MFM
;	formats.
;		
;		   Western Digital Corp
;		      P.O. Box 2180
;	           3128 Redhill Avenue
;		  Newport Beach, Cal 92663
;		      (714) 557-3550
;
;	The following features of { DDD } are utilized: 
;		
;			Radial alignment check
;			Azimuth alignment check
;			Centering 
;			Stepper Hysteresis
;			Index Timing
;
;	The RPM check is not a function of the { DDD }.
;
;	Original configuration (Version 1.0):
;
;	A. Hazeltine 1500 Terminal   
;	B. 8080 Assembly language
;	C. Timing based on 4mhz Z80 processor
;	D. Direct Console I/O to CP/M 80
;	E. Disk operations written for Dysan's
;	   Single Card Computer.
;	F. Diagnostic Disk (808-100)
;
;



;	****************************************************************
;
;	PROGRAM SOURCE CODE:
;
;	title	'Drive Diagnostic Program for CP/M 80 1/15/83'
;
;	File ddd.asm
;

wboot	equ	0		; warm boot address

bdos	equ	5		; jump address for bdos calls


**********************
*** "CONDITIONALS" ***
**********************
;
;	Choose the appropriate assemble time options for your system,
;	or use this space to add new system options.
;
true	equ	0ffffh
false	equ	not true
;
Dysan	equ	false	;set this true for Dysan controller
CCS	equ	true	;set this true for CCS 2422 controller 
			;	programmed i/o transfer, etc.
lineclr	equ	false	;set this true if your console has
			;	a clear-to-end-of-line command
Hazel	equ	false	;set this true for Hazeltine 1500 terminal
			;	(requiring "lead-in" to commands)
Loren	equ	true	;set this true for Loren's homebrew terminal...
;
;ADD CONDITIONAL OPTIONS FOR YOUR ENVIRONMENT HERE...
;
;

	
********************************
*** "MACRO CALL BIOS DIRECT" *** 
********************************
;
;	This macro was used in version 1.0 to Link console I/O
;	only, the disk i/o routines also may be linked
;	to CP/M 2.2 with this macro.
;
;	e.g.  gobios 24		; select drive
;
;
;	Function:
;	Loads Warm boot address to bios
;	and computes offset to routine.
;
;
;gobios	macro	@func		
;	lhld	wboot+1		; Warm boot address
;	lxi	d,@func		; Offset
;	dad	d		; Add offset
;	pchl			; Go to bios routine
;	endm


***************************
*** "CONSOLE FUNCTIONS" ***
***************************

;	The following are direct console commands
;	which can be altered for most consoles.

;	note:
;	     The text print routine must be altered
;	     if "Row" is sent before "Column" or 
;            bias is needed.

	if	Hazel		;version 1.0
add$cur equ	17		; address cursor command
clr$co	equ	28		; clear to foreground spaces
lead$in	equ	126		; console lead-in 
end$ln	equ	15		; clear to end of line
	endif

	if	Loren		;version 1.1
add$cur equ	01		; address cursor command
clr$co	equ	05		; clear to foreground spaces
	endif

cr	equ	0dh		; carriage return
lf	equ	0ah		; line feed
esc	equ	1Bh		; escape
bs 	equ	8		; back space
bell	equ	7		; audio alert


****************************************
*** "FLOPPY CONTROLLER PORT EQUATES" ***
****************************************

;	Change the following Port assignments for
;	Your system.
;
;	"FDC"  Acronym  Floppy Disk Controller
;
;	FDC port assignments:
;
	if	Dysan		;version 1.0
fdc 	equ	0f8H		; Base port address FDC
;
cmd	equ	fdc		; command reg.
stat  	equ	fdc		; status reg.
trk	equ	fdc+1		; track reg.
sec	equ	fdc+2		; sector reg.
data	equ	fdc+3		; data reg.
dma 	equ	fdc+4		; Dma controller
dsel	equ	fdc+5		; drive select
	endif

	if 	CCS		;version 1.1
fdc 	equ	30H		; Base port address FDC
;
cmd	equ	fdc		; command reg.
stat  	equ	fdc		; status reg.
trk	equ	fdc+1		; track reg.
sec	equ	fdc+2		; sector reg.
data	equ	fdc+3		; data reg.
dma 	equ	004CH		;memory address of pointer to 
;                                          sector buffer
dsel	equ	fdc+4		; drive select port:
				;output BX for single density
				;       FX for double density
				;   where X = 1 for drive A
				;             2 for drive B
				;             4 for drive C
				;             8 for drive D
	endif
	
************************************
*** "FLOPPY CONTROLLER COMMANDS" ***
************************************

;	These are common to most systems using the 1793.
;	sdma is a Dysan controller command, ignored in V. 1.1.

clear	equ	0d0h		; clear FDC
sdma    equ	87h		; Start Dma Transfer
rsec	equ	80h		; read sector
raddr	equ	0c0h		; read address
seek	equ	18h		; seek track
restore	equ	8		; home Head(s)
sdelay	equ	4		; seek delay flag

*************************************
*** "FLOPPY CONTROLLER VARIABLES" ***
*************************************

rate	equ	1		; step rate 
retry	equ	1		; read retries
fdelay	equ	11	; FDC delay
			; see "delay" routine - this value is for
			; 4 Mhz. Z-80;  adjust here or in "delay"
			; to suit your clock and processor...
indxbyt	equ	2	; byte in status reg. when index hole
			; is passing sensor
busybyt	equ	1	; byte in status reg. when controller
			; is busy
drqbyt	equ	2	; byte in status reg. when data is 
			; waiting to be read by the computer

******************************
*** "DDD DISKETTE EQUATES" *** 
******************************

;	Adjust to match your diskette size and format.

ttrk 	equ	76		; total number of tracks
sectors	equ	26		; sectors per track
				; 26 for 8" DDD, 16 for 5.25" DDD
lneg	equ	sectors+2		; last neg. sector +2
lpos	equ	sectors+1		; last pos. sector +2
tsec	equ	(sectors/2)-1	; centering test

	if 	Dysan
ref	equ	798		; reference time (single Den)
				; (used in "index 7")
	endif

	if	CCS
ref	equ	24eh		; experimentally determined...
	endif



***************************
*** "MAIN PROGRAM LOOP" *** 
***************************

	org	100h
;	====	====
	lxi	sp,stack	; init stack
	call	select		; select drive
;
main:
	lxi	sp,stack	; reset stack 
	call	cls		; clear display
	lxi	h,me1		; display Menu..
	call	text
	call	ci		; selection?
	cpi	'R'		; "Radial"
	jz	radial 		   
	cpi	'A'		; "Azimuth"
	jz	azimuth
	cpi	'C'		; "Centering"
	jz	center
	cpi	'H'		; "Hysteresis"
	jz	hyster 
	cpi	'S'		; "RPM"
	jz	rpm
	cpi	'I'		; "Index"
	jz	index
	cpi	'D'		;"Drive Select"
	jnz	ex
	call	select
	jmp	main		;new drive selected - get option

ex:	cpi	'E'		; "Exit to DOS"
	jz	exit 		
	mvi	a,bell		; Not valid
	call	co
	jmp	main		; try again...


**********************
*** " EXIT TO DOS" ***
**********************

exit:
	call	cls		; clear display
	jmp	wboot

*************************
*** "CONSOLE  STATUS" ***   
*************************

;	returns with zero status flag set.
 
cstat:
	push	h		; save all registers
	push	d
	push	b
;	call	cstat1		; Data ready?
	mvi	c,11		; BDOS console status
	call	bdos		; function call added for V1.1
	pop	b
	pop	d
	pop	h
	ora	a
	ret
;cstat1:
;	gobios	3		; macro

***********************
*** "CONSOLE INPUT" *** 
***********************
;
;	Returns character in "A" reg.
ci:
	push	h		; Save all registers
	push	d
	push	b
;	call	ci1		; take  character 
	mvi	c,1		; BDOS console input
	call	bdos		; function call added for V1.1
	pop	b
	pop	d
	pop	h
	cpi	esc		; Exit?
	jz	main 		; YES!
	cpi	'a'		; convert to upper case
	rc			; only...
	cpi	'{'
	rnc
	ani	'^'+1		
	ret

;ci1:
;	gobios	6		; macro



************************
*** "CONSOLE OUTPUT" *** 
************************
;
;	Enter with character in "A" reg.

co:
	push	psw
	push	h		; save all registers
	push	d
	push	b
;	mov	c,a		; Pass char in "C" reg
	mov	e,a		; Pass char in "E" reg for V1.1
	mvi	c,6		; BDOS direct console i/o
	call	bdos		; function call added for V1.1
;	call	co1		
	pop	b
	pop	d
	pop	h
	pop	psw
	ret

;co1:
;	gobios	9		; macro


********************
*** "LINE INPUT" ***
********************

;	used to input data greater then one
;	character which is terminated by "CR".
;	(used only by "offset:" directly below here...)

getln:
;	lxi	d,buffer	; input buffer

; Following code added to V1.1 to use standard BDOS call for Line Input:
	lxi	d,inbuf		; input buffer in BDOS 10 format
	mvi	c,0Ah		; Console Input Line function
	call	bdos		; added for V 1.1
	lhld	incnt		; get # of characterrs read
	mvi	h,0		; incnt is only one byte...
	xchg			; move to de reg
	lxi	h,buffer	; get text buffer address
	dad	d		; increment buffer pointer by # chars
	mvi	m,0dh		; place "cr" after valid chars
				; 	as V1.0 expects...
	ret
;
;gl1:	
;	call	ci		; Wait for Input
;	cpi	lf		; Line feeds Not allowed
;	jz 	gl1
;	cpi	'_'		; treat as back space
;	jz 	back
;	cpi	bs		; check for back space
;	jz 	back
;	cpi	7fh		; Delete char?
;	jz 	back
;	cpi	cr		
;	jz 	gl2
;	cpi	' '
;	jc 	gl1		; control Characters Not allowed
;;
;gl2:
;	stax	d		; store char
;	inx	d		; next address
;	call	co		; echo char
;	cpi	cr		; end of Line?
;	rz			; Yes!
;	lxi	h,buffer+4	; end of Buffer
;	call	dehl		; check 
;	jnz 	gl1		; No!
;	jnz 	gl1		; No!
;	jnz 	gl1		; No!
;;
;back:
;	lxi	h,buffer	; can backup ?
;	call	dehl
;	jz 	gl1		; NO!
;	dcx	d		; Backup text pointer
;	mvi	a,bs		; backup cursor
;	call	co
;	mvi	a,' '		; store Space
;	call	co
;	mvi	a,bs		; adjust cursor
;	call	co
;	jmp	gl1		; New char

**********************************
*** "BIAS FROM SELECTED TRACK" ***
**********************************
;
;	Sets the required offset for Hysteresis
;	test.

offset:
	call	cls		; clear display
	lxi	h,me6		; OFFSET?
	call	text
	call	getln		; Input offset
	call	getnum		; convert to hex
	cpi	cr		; at end of line?
	jnz	offset1		; error...
	mov	a,h		; check Limits 
	ora 	a
	jnz	offset1
	mov	a,l
	cpi	ttrk+1		; Greater then last track?
	jnc	offset1
	sta	bais		; save offset 
	ret
;
offset1:
	mvi	a,bell		; alert operator
	call	co
	jmp	offset


*******************************
*** "INPUT TRACK LOCATIONS" *** 
*******************************

;	Input track locations for Radial
;	Hysteresis,Centering and Index tests.
;	"B" contents Upper Limit upon entry.

inp$trk:
	call	cls		; clear display...
	call	text
;
inp$trk1:
	call	ci		; waiting...
	cmp	b  		; within limits?
	jnc	inp$trk2	; no... 
	sui	'A'		
	jc	inp$trk2	; try again  
	lhld	temp     	; table pointer
	mvi	d,0
	mov	e,a
	dad	d		; add offset
	mov	a,m		; load track
	jmp 	track		; seek to track
;
inp$trk2:
	mvi	a,bell		; alert
	call	co
	jmp	inp$trk1	; try again...

***********************************************
*** "RADIAL AND HYSTERESIS TRACK LOCATIONS" ***
***********************************************

rh$tbl
	db	0		
	db	3
;	Note:  some Dysan spec sheets list track 5 rather 
;	than 3 as an index track - my Revision A DDD definitely
;	uses track 3...  LA.
	db	38
	db	41
	db	70
	db	73

***************************   
*** "INDEX TRACK TABLE" *** 
***************************   

ix$tbl:
	db	0
	db	76

*************************
** "CENTERING TRACKS" ***
*************************

cen$tbl:
	db	35
	db	44
	db	47


*******************************
*** "PRINT DECIMAL NUMBERS" *** 
*******************************
;
;	Enter with number to be printed in
;	'DE' reg.

pnum:
	push	h		; Setup Stack
	lxi	h,10		; Terminator...
	push	h
	push	h
;
pn1:	
	call	div16		; Divide Number By (10)
	mov	a,d		; Check result
	ora	e		; = 0
	jz 	pn2
	xthl
	dcr	l
	push	h
	lxi	h,10
	jmp	pn1		; Divide Again
;
pn2:
	pop	d		; Display Values
	mov	e,l
;
pn3:
	mov	a,e		; Check for Terminator (10)
	cpi	10
	pop	d		; Next digit 
	rz
	adi	'0'		; Add ascii Bias
	call	co
	jmp	pn3		


****************************
*** "16 BIT SUBTRACTION" *** 
****************************
;
;	Subtract "DE" from "HL"
subde:	
	mov	a,l		
	sub	e
	mov	l,a		
	mov	a,h		
	sbb	d
	mov	h,a		
	ret


************************************************
*** "CONVERT ASCII DECIMAL NUMBER TO BINARY" ***    
************************************************
;
;	Returns 16 bit hex value in "HL" regs.

get$num:
	call	sksp		; Skip Spaces and Return Char
	lxi	h,0		; Clear counter
	mov	b,h		; Clear "B"
;
get$num1:
	cpi	cr		; end of line?
	cpi	'0'		; less than
	rc			; yes Error!
	cpi	':'		; Upper Limit
	rnc			; Returns "CR"
	mvi	a,0f0h		; mask Upper Nibble
	ana	h
	rnz			
	inr	b		; +1
	push	b		; Save count..
	mov	b,h
	mov	c,l		; Swap "HL" with "BC"
	dad	h
	dad	h
	dad	b
	dad	h
	ldax	d		; Load Same Char..
	inx	d		; next Char 
	ani	0fh		; Mask Lower Nibble
	add 	l
	mov	l,a		; save result
	mvi	a,0		; Clear "A"
	adc	h		; Add carry
	mov	h,a
	pop	b		; restore counter..
	ldax	d		; Load next Char..
	jmp	getnum1 
	
*****************************************
*** "SKIP OVER SPACES IN TEXT BUFFER" *** 
*****************************************

sksp:
	lxi	d,buffer	; point to text buffer
;
sksp1:
	ldax	d  		; check for Space
	cpi	' '		; First Non Space return
	rnz
	inx	d
	jmp	sksp1

*****************************
*** "COMPARE "DE" TO "HL" ***   
*****************************

dehl:
	mov	a,l		; compare "E" to "L"
	cmp	e		; If not zero return
	rnz
	mov	a,h
	cmp	d 
	ret



**********************************
*** "16/24 BIT DIVIDE ROUTINE" ***
**********************************

;	Divide "HL" by "DE"
;

div16:	
	xra	a		; optional 16 bit divide
;
div24:	
	sta	msb		; Normal 24 bit divide
	shld	msb1
	lxi	h,msb2
	mvi	m,24+1
	lxi	b,0
	push	b
div25:	
	mov	a,e
	ral
	mov	e,a
	mov	a,d
	ral
	mov	d,a
	lda	msb
	ral
	sta	msb
	dcr	m
	pop	h
	rz
	mvi	a,0
	aci	0
	dad	h
	mov	b,h
	add	l
	lhld	msb1
	sub	l
	mov	c,a
	mov	a,b
	sbb	h
	mov	b,a
	push	b
	jnc	div26
	dad	b
	xthl
;
div26:	
	lxi	h,msb2
	cmc
	jmp	div25



******************************
*** "CLEAR CONSOLE DISLAY" *** 
******************************

;	Clear console to foreground spaces.
 
cls:
	if 	Hazel
	mvi	a,lead$in	; lead in 
	call	co
	endif

	mvi	a,clr$co	; clear to foreground spaces
	jmp 	co

****************************
*** "CLEAR DISPLAY LINE" ***
****************************

cline:
	if 	lineclr
	mvi	a,0		; starting column
	sta	column
	lxi	h,set$cur	; set cursor
	call	text
	endif
	
	if 	Hazel AND lineclr
	mvi	a,lead$in	; lead in byte
	call	co
	endif

	if	lineclr
	mvi	a,end$ln	; clear to end of line
	call	co
	endif

	if	NOT lineclr
	mvi	a,11		; starting column
	sta	column
	lxi	h,set$cur	; set cursor
	call	text
	lxi	h,blanks	;address of a string of 56 blanks...
	call	text
	endif

	ret

*************************
*** "FATAL ERROR MSG" ***
*************************

fatal:
	if 	lineclr
	call	cline		; clear line
	endif

	mvi	a,30		; column position
	sta	column
	lxi	h,set$cur
	call	text
	lxi	h,me2		; Fatal error msg
	call	text
	ret


******************************
*** "PRINT STRING OF TEXT" *** 
******************************

;	Enter with "HL" pointing to text string,
;	terminate string with Null.
;
;	Direction cursor position is used for displays.
;	The value (-1) at the start of string indicates 
;	to this routine
;	that column and row position will follow.
;	This format does not necessarily go out to 
;	your terminal.   If your terminal needs row sent before column, 
;	or a constant bias added (0,0 is not the upper left
;	corner of the screen), you'll have to invent code
;	within this routine to accomplish that.
;
;	This is the internal representation format:
;	     db -1,50,10,'NOW IS THE TIME'
;		 ^  ^  ^
;		 |  |  |_Row position (add bias if needed)
;		 |  |_Column position (add bias if needed)
;		 |_Flag (send console lead-in sequence.

text:
	mov	a,m		; load char.
	ora	a		; end of string?
	rz			; yes
	cpi	(-1) AND 0FFH	; position cursor?
				; "and offh" added for ASM compatibility
	jz	text1		; yes
	inx	h		; next char.
	call	co		; output
	jmp	text
;
text1:
	inx	h		; move passed command

	if 	Hazel
	mvi	a,lead$in	; leading for console
	call	co		; issue.
	endif

	mvi	a,add$cur	; address cursor
	call	co
	mov	a,m		; column position...
	inx	h
	call	co
	mov	a,m		; row position
	call	co
	inx	h		
	jmp	text		 

*************************
*** "CENTERING CHECK" *** 
*************************

;
;	Centering test requires the FDC to read
;	all the sectors before diskette centering
;	is consider OK.

center:
	lxi	h,cen$tbl	; track table
	shld	temp
	lxi	h,me9		; tracks with 
	mvi	b,'D'		; limit
	call	inp$trk		; seek track  
	call	cls		; clear display
	lxi	h,me10		; centering msg.
	call	text
	lxi	h,me15		; frame
	call	text
	lxi	h,me11		; New track msg
	call	text
;
center1:
	call	rd$trk		; read centering track
	mvi	a,10		; set row position
	sta	row		
	jc	center3		; fatal error..

	if 	lineclr
	call	cline		; clear line
	endif

	mvi	a,30		; set cursor...
	sta	column		; column position
	lxi	h,set$cur
	call	text
	lda	diff 		; must = 0
	ora	a
	lxi	h,me3		; "RE-CLAMP DISKETTE"
	jnz	center2
	mov	a,c
	cpi	tsec      	; all sec read? 
	jnz	center2
	lxi	h,me4		; "CENTERING OK"
;
center2:
	call	text
	call	cstat		; abort?
	jz	center1
	call	ci
	cpi	' '		; new track?
	jnz	center1		; no...
	jmp	center		; yes..
;
center3:
	call	fatal		; fatal error
	jmp	center2


*********************************
*** "AZIMUTH ALIGNMENT CHECK" *** 
*********************************

azimuth:
	call	cls		; clear display...
	mvi	a,76		; seek to azimuth track
	call	track		; move...
	lxi	h,me12		; type of test msg
	call	text
	lxi	h,me15		; frame
	call	text
;
azimuth1:
	lxi	h,azi$tab	; set translation table 
	shld	xpoint		; pointers
	shld	ypoint
	call	rd$trk		; read azimuth track
	mvi	a,10		; set row position
	sta	row		
	jc	azimuth3	; fatal error...

	if	lineclr
	call	cline		; clear line
	endif

	mvi	a,20		; Display negative angle
	sta	column
	lxi	h,set$cur	; set cursor
	call	text
	mvi	a,'-'		; direction of angle
	call	co		; output...
	mvi	a,' '		; space
	call	co
	lhld	ypoint		; translation
	mov	e,m		; data negative...
	mvi	d,0
	call	pnum		; display
	lxi	h,me5		; print minutes
	call	text
	mvi	a,45		; Display Positive angle
	sta	column
	lxi	h,set$cur
	call	text
	mvi	a,'+'		; direction of angle
	call	co		; output...
	mvi	a,' '		; space
	call	co
	lhld	xpoint		; translation
	mov	e,m		; data positive..
	mvi	d,0
	call	pnum		; display
	lxi	h,me5		; print minutes
	call	text
;
azimuth2:
	call	cstat		; abort?
	jz	azimuth1
	call	ci		; test...
	jmp	azimuth1	; no..
;
;	Fatal error Has occurred
;
azimuth3:
	call	fatal		; fatal read error
	jmp	azimuth2


********************************
*** "RADIAL ALIGNMENT CHECK" *** 
********************************


radial:
	lxi	h,rh$tbl	; table pointer
	shld	temp
	lxi	h,me7		; track display..
	mvi	b,'G'		; limit  
	call	inp$trk		; select track and seek
	call	cls
	lxi	h,me8		; print scale...
	call	text
	lxi	h,me11		; Space bar msg
	call	text
;
radial1:
;
	lxi	h,rad$pos	; radial positive 
	shld	xpoint		; cursor table
;
	lxi	h,rad$neg	; radial negative
	shld	ypoint		; cursor table
;
	call	rd$trk		; read radial track
	mvi	a,11		; set row position
	sta	row
	jc	radial4		; Fatal error has occurred
	call	cline		; clear line (1)
	lda	row		
	push	psw		  
	inr	a		; clear line (2)
	sta	row		
	call	cline
	pop	psw		; reset line position
	sta	row
	lhld	ypoint 		; negative 
	mov	a,m
	sta	column		; position cursor
	mov	b,a 
	lxi	h,set$cur	
	call	text
	mvi	a,'^'		; set pointer
	call	co
	lhld	xpoint
	mov	a,m		; positive position
	sta	column 		
	mov	c,a		; save cursor position 
	lxi	h,set$cur	; set cursor
	call	text
	mvi	a,'^'
	call	co
	mov	a,b		 
	sta	column		; reset column position
	lda	row		; down one line
	inr	a
	sta	row


************************************
*** "SET POINTERS AND DRAW LINE" ***
************************************

;	used to draw the graphic display of the
;	radial error.

	lxi	h,set$cur	; position cursor
	call	text
	mov	a,c
	sub	b		; line length
	dcr	a		; less (1)
	mov	b,a
	mvi	a,'|'		; pointer...
	call	co
;
radial2:
	mvi	a,'_'		; jointing line
	call	co
	dcr	b		; line length -1
	jnz	radial2
	mvi	a,'|'
	call	co
;
radial3:
	call	cstat		; check for abort
	jz	radial1		; read again
	call	ci		; new track?
	cpi	' '		
	jnz	radial1		; no...
	jmp	radial		; new track...
 
****************************
*** "FATAL RADIAL ERROR" ***
****************************

radial4:

	if	lineclr
	call	cline		; clear display
	lda	row		; next line
	inr	a		
	sta	row
	call	cline
	endif

	call	fatal		; fatal read error
	jmp	radial3		; abort?


**********************************
*** "STEPPER HYSTERESIS CHECK" ***
**********************************

;
;	This routine uses one of the progressive offset
;	tracks to determine the stepper motor hysteresis.

hyster:
	lxi	h,rh$tbl	; table pointer
	shld	temp
	lxi	h,me7		; track msg
	mvi	b,'G'		; limit
	call	inp$trk		; seek track
	call	offset		; offset from
	call	cls		; selected track.
	lxi	h,me14		; display test
	call	text
	lxi	h,me15		; frame
	call	text
	lxi	h,me11		; new track Msg.
	call	text
;
hyster1:
	lda	bais		; offset from track
	mov	b,a
	lda	ctrk		; save current track
	sta	savtrk
	add	b		; add bais to current track
	cpi	ttrk  		; within limits?
	jc 	hyster2		; OK!
	mvi	a,ttrk  	; set last track
;
;	Move to (ID) inside diameter

hyster2:
	call	track		; seek to track
	lda	savtrk		; back to test track
	call	track		; seek...
	call	rd$trk		; read track...
	mvi	a,10		; set row 
	sta	row
	jc	hyster8		; fatal error!!!
	lda	diff 		; difference
	sta	hyerr		; save the difference

;	Move to (OD) outside Diameter

	lda	bais		; tracks to move
	mov	b,a
	lda	ctrk		; current track
	sub	b
	jnc	hyster4		; Ok to move
	xra	a		; set to track (0)

;
hyster4:
	call	track		; seek to track
	lda	savtrk		; back to test track
	call	track		 
	call	rd$trk		; read track 
	mvi	a,10		; set row 
	sta	row
	jc	hyster8		; fatal Error!!
	lda	hyerr		; load error First 
	mov	c,a		; read operation
	lda	diff 		; last reading
	sub	c
	jp	hyster6
	cma	
	inr	a
;
hyster6:
	call	hyster9
;
hyster7:
 	call	cstat		; abort?
	jz	hyster1		; re-test
	call	ci		  
	cpi	' '		; new parameters
	jz	hyster 
	jmp	hyster1		; new track and offset
;
hyster8:
	call	fatal		; fatal read error
	call	home		; recal.drive
	jmp	hyster7


**********************************
*** "DISPLAY HYSTERESIS ERROR" ***
**********************************
;
;	Presently setup for 48 tpi drives
;	with increments in .5 millinches.

hyster9:
	push	psw		; save error

	if 	lineclr
	call	cline		; clear display
	endif

	mvi	a,25	 	; set column
	sta	column
	lxi	h,set$cur
	call	text
	lxi	h,me16		; Hysteresis error msg
	call	text
	pop	psw
	ora	a
	jz 	hyster11
	mov	c,a		; count
	mvi	b,5		; increments
	xra	a		; clear acc.
;
hyster10:
	add	b
	daa			; decimal adjust
	dcr	c
	jnz	hyster10
;
hyster11:
	push	psw
	ani	0f0h		; mask upper nibble
	rar!rar!rar!rar
	adi	'0'		; add ascii bais
	call	co
	mvi	a,'.'		; decimal point
	call	co
	pop	psw
	ani	0fh
	adi	'0'
	call	co
 	ret



**********************
*** "INDEX TIMING" *** 
**********************

;
;	This function computes the time from leading
;	edge of index to first sector ID mark
;	and displays it in 10.0 Us. increments
;	note:
;	     (Dysan AAD disk) is used for reference.
index: 
	mvi	a,10		; set row
	sta	row
	lxi	h,ix$tbl	; track table
	shld	temp
	lxi	h,me13		; track locations
	mvi	b,'C'
	call	inp$trk		; move to Index track
	call	cls		; clear display..
	lxi	h,me17		; display scale
	call	text
	lxi	h,me15
	call	text
	lxi	h,me11		
	call	text
;
index1:
	lxi	h,0		; clear counter
	shld	temp		
	mvi	c,5		; average (5) readings
;
index2:
	call	clpend		; clear FDC
	call	prg$dma		; program controller
	lxi	d,0		; clear counter
;
index3:
	in	stat		; wait for next Index
	ani	indxbyt		
	jnz 	index3

;	Compute time from index to ID 

index4:
	in	stat		; loop until next
	ani	indxbyt		; index...
	jz 	index4		
;
;	Read address..
;
	nop			; 1.00
	mvi	a,raddr		; 1.75
	out	cmd		; 2.75
	call	delay		; [ 50 usec ]

	if	Dysan
	mvi	a,sdma		; 1.75
	out	dma		; 2.75
	endif

	if	CCS
;
;	10 Usec Test cnt. loop
index5:
	inx	d		; 1.50 [ counter ]
	inx	h		; 1.50
	in	stat		; 2.75 
	ani	drqbyt		; 1.75 - loop until drq set...
	jz	index5		; 2.50
	LHLD	DMA
	IN	DATA
	MOV	M,A
	INX	H
	IN	DATA
	MOV	M,A
	INX	H
	IN	DATA
	MOV	M,A	
	INX	H
	IN	DATA
	MOV	M,A
	INX	H
	IN	DATA
	MOV	M,A
	INX	H
	IN	DATA
	MOV	M,A
	endif


	if 	Dysan
;
;	10 Usec Test cnt. loop
index5:
	inx	d		; 1.50 [ counter ]
	inx	h		; 1.50
	in	stat		; 2.75 
	ani	busybyt		; 1.75 - loop until not busy
	jnz	index5		; 2.50
	endif
;
index6:
	lxi	h,6		; adj. over head
	dad	d		; error (60usec)
	xchg
	lhld	temp
	dad	d		; add cnt
	shld	temp
	dcr	c		; next reading
	jnz	index2
	xchg
	lxi	h,5		; divide by 5
	call	div16 
	dad	d		; add remainder
	xchg
	lxi	h,0		; counter...
	lda	secbuf+2	; must contain sec (1) ID
	cpi	1
	jnz	index9		; out of range
	mvi	a,10		; loop time * cnt
index7:
	dad	d
	dcr	a
	jnz	index7
	lxi	d,ref   	; Timing ref  
				; Value of ref is in DDD variable
				;equates... it is subtracted from
				;the measured # of microsec. here
				;to adjust timing to a standard
				;Analog Alignment Diskette...
	; If you have a 4 Mhz. Z-80 and single density DDD
	; and are using the Dysan environment, 798 is the 
	; magic number.  Otherwise you'll have to "cut and try"
	; and without the AAD you'll have to guess...
	; (A relative measure is better than no measure...)
	call	subde		
	xchg			
	jnc	index8
	mov	a,e
	cma
	mov	e,a
	mov	a,d		; negate "DE"
	cma
	mov	d,a
	inx	d
	lxi	h,200		; 200 - error
	call	subde
	jnc	index9
	lxi	h,0		; out of range
	jmp	index9
;
index8:
	lxi	h,200		; 200  + error
	dad	d
;
index9:
	xchg
	push	d

	if	lineclr
	call	cline		; clear line
	endif

	mvi	a,25
	sta	column
	lxi	h,set$cur	; position cursor
	call	text
	lxi	h,me18		; time in MS.
	call	text
	pop	d
	call	pnum		; display time...
	call	cstat		; abort?
	jz	index1		; re-test
	call	ci		; esc?
	cpi	' '		; new track?
	jz	index 		; yes..
	jmp	index1		; new track...
 

*****************************
*** "CHECK SPINDLE SPEED" *** 
*****************************
;
;	All timing is based on 4mhz Z80 Cpu
;
rpm:
	call	cls		; clear display
	lxi	h,me19		; test performed
	call	text
	lxi	h,me15		; frame...
	call	text
	mvi	a,10		; set row
	sta	row
;
rpm1:
	call	rpm2		; compute time in 100us increments
	shld	temp 		; store count

	if	lineclr
	call	cline		; clear line
	endif

	mvi	a,19		; set cursor  
	sta	column
	lxi	h,set$cur
	call	text
	lhld	temp
	xchg			; convert to milliseconds
	lxi	h,10
	call	div16			  
	push	h		; Save remainder
	call	pnum
	mvi	a,'.'		; decimal point
	call	co     
	pop	h
	xchg
	call	pnum		; fraction
	lxi	h,me20		; milliseconds msg
	call	text
	mvi	a,50
	sta	column
	lxi	h,set$cur
	call	text
	lhld	temp 		; convert to RPM 
	mvi	a,9		; divide By 600,000
	lxi	d,27c0h
	call	div24
	push	h		; remainder
	call	pnum
	mvi	a,'.'		; fraction
	call	co
	pop	h
	xchg
	call	pnum
	lxi	h,me21		; rpm msg
	call	text
	call	cstat		; abort?
	jz	rpm1		; No..
	call	ci		; Esc key?
	jmp	rpm1		; No..


*******************************
*** "INDEX TO INDEX TIMING" ***
*******************************

;
;	With 4 Mhz. Z-80,
;	returns time in 100 Us increments to caller
;	in "HL" regs.

rpm2:
	call	clpend  	; Clear pending commands
	lxi	h,0		; Clear Counter
rpm3: 
	in 	stat   		; Loop Until Index
	ani	2		; Mask All But Index Bit
	jnz 	rpm3 		; No Index
rpm4:
	in 	stat   		; if Index...
	ani	2		; Wait for No Index
	jz  	rpm4		; In Index Hole

;	Add index hole to count
rpm5: 
	call	rpm7 		; 4.25
	in 	stat   		; 2.75
	ani	2		; 1.75
	jnz	rpm5 		; 2.50
				; Total = 11.25
;	Count until  next Index
 
rpm6: 	
	call	rpm7 		; 4.25
	in 	stat		; 2.75
	ani	2		; 1.75
	jz	rpm6 		; 2.50
	ret			; total = 11.25

*************************
*** "RPM TIMING LOOP" *** 
*************************
;
;	The loop time must be adjusted for 100us  
;	increments at your clock speed with your processor.
;	
;	note:	"RPM5 or RPM6" loop time must be counted.
;

rpm7:				
	inx	h		; 1.50 
	mvi	a,22		; 1.75 
;
rpm8: 
	dcr	a		; 1.00  (22 * 1.00) = 22 Usec
	jnz	rpm8 		; 2.50  (22 * 2.50) = 55 Usec
	inx	d		; 1.50
	inx	d		; 1.50
	inx	d		; 1.50
	inx	d		; 1.50
	ret			; 2.50
				; total = 88.75  


************************
*** "READ DDD TRACK" *** 
************************
;
;	Att: Main read routine for program.
;	     ==============================
;
;	Reads the Positive and Negative offset
;	sectors and returns pointers to the   
;	translation tables set by caller.
;

rd$trk:
	MVI	A,7	;Upper case code adds a simple display of
			;	last sector read (+ & -), giving
			;	? and @ if first sectors fail
			;	and A thru Z representing the 26
			;	possible sectors on an 8" disk
			;	or A thru P for a 5.25" disk
	STA	ROW
	MVI	A,39
	STA	COLUMN
	LXI	H,SET$CUR
	CALL	TEXT
	mvi	c,lpos		; last sector
	mvi	a,1		; beginning sector positive
	call	rd$sec 		; read positive offsets
	ADI	3eH	; translate sector # to alpha code */
	CALL	CO	; display on console  */
	SUI	3eH	; return to sector # */
	cpi	1		; unable to read
	jz 	rd$trk2		; first sec?
	sta	diff 		; store last sector tested
	mvi	c,lneg
	mvi	a,2		; beginning sector negative
	call	rd$sec 		; read negative offsets 
	ADI	3eH
	CALL	CO
	SUI	3eH
	cpi	2		; fatal error?
	jz	rd$trk2		; set error flag
;
;	Positive sector Translation
;
	lda	diff  
	inr	a		; adj. sector Num.
	sui	4		
	rar			; divide by two
	lhld	xpoint		; translate Table pointer
	mvi	d,0		; setup for Offset
	mov	e,a 
	dad	d		; add offset
	shld	xpoint		; set pointer
;
;	Negative Sector Translation

	in	sec		; last sector
	sui	4		
	rar 			; divide by two
	mov	c,a
	sub	e		; diff. for Hysteresis
	sta	diff 	
	mov	e,c		; offset
	lhld	ypoint		; translation table pointer
	dad	d		; offset in table
	shld	ypoint		; set pointer
	ora	a		; clear carry
	ret

;	Set fatal error Flag, caller processes
;	the error.

rd$trk2:
	stc			; carry = Fatal error
	ret
	


*******************************************
*** "READ SECTORS BY INCREMENTS OF TWO"	***
*******************************************

;
;	Enter with first sector to be read in 'A' reg.
;	Returns to caller on Error or Last sector.
;	note:
;	    Z flag set if good read else Nz
rd$sec: 
	call	read		; read sector
	in	sec  		; current sector
	rnz
	adi	2
	out	sec
	cmp	c		; last sec?
	rz			; yes...
	jmp	rd$sec

********************************************************
***  "THE FOLLOWING ARE HARDWARE DEPENDENT ROUTINES" ***
********************************************************
;
;
**********************
*** "DRIVE SELECT" *** 
**********************
;
;	The drive select routine must be expanded  
;	for selected systems. 

select:

	if	Dysan
	mvi	a,21h		; select bits
	out	dsel		; select drive...
	endif


	if	CCS	;The upper case code performs drive 
			; selection on the CCS 2422 controller
			; for single side double density...
	CALL	CLS	; clear console */
	LXI	H,SELMSG
	CALL	TEXT	; print drive selection request */
	CALL	CI	; get response */
	CPI	'A'	; accept A,B,C,D, as responses */
	JZ	SELECT1
	JC	SELECT
	CPI	'B'
	JZ	SELECT1
	CPI	'C'
	JZ	SELECT3
	CPI	'D'
	JZ	SELECT4
	JMP	SELECT	; repeat if invalid choice */

	
SELECT4:ADI	3	; make low nybble an 8 */
SELECT3:INR	A	; make a 4 */
SELECT1:SUI	'@'	; make B into 2 or A into 1 */
	ORI	0F0H	; add high nybble: */
			; F for double density, B for single
	STA	SELPT	; store select bits for future use... */
	OUT	DSEL
	MVI	A,40H	; select side 0...  00 selects side 1... */
	OUT	04	; secondary control port */
	endif
	
	jmp	home		; home drive

*******************************
*** "SEEK HEAD(S) TO TRACK" *** 
*******************************
;
;	Enter with new track location in
;	'A' register.

track:
	out	data		; new track
	call	clpend		; clear FDC
 	mvi	a,seek+rate	; seek command + step rate
;
track1:
	out	cmd		; issue...

	if 	Dysan
	call	delay		; delay for FDC	
	endif

	if	CCS	;This controller seems to need more 
			; delay - I can't explain why... LA.
	call	delayB		; delay for FDC	
	endif

;
track2:
	in	stat		; busy ?
	rrc			; test
	jc	track2		; still busy...
	mvi	a,sdelay	; set seek delay bit
	sta	dflag
	in 	trk		; set current track
	sta	ctrk
	ret

	if	CCS
DELAYB:	PUSH	B	; extra delay for CCS controller... */
	LXI	B,2000H
	
DELAYC:	DCX	B
	MOV	A,C
	ORA	B
	JNZ	DELAYC
	POP	B
	RET
	endif


***************************************
*** "RESTORE HEAD(S) TO TRACK ZERO" ***
***************************************

home:
	call	clpend		; clear FDC
	mvi	a,restore+rate	; restore command + step rate
	jmp	track1		; issue command...

*****************************
*** "READ SECTOR ROUTINE" *** 
*****************************

;	Enter this routine with the sector to
;	be read in the 'A' register.
;
;	This routine will keep trying to read
;	the sector until retry count equals zero.
;
;	The 1793 controller has a built-in automatic
;	four retries to read ID, so the value set in
;	the equate (RETRY) is equal to [ 4 * retry + 1].

read:
	out	sec		; set sector  
	mvi	e,retry		; to read
;
read1:
	call	clpend		; clear FDC
	call	prg$dma		; program "DMA" controller

	if 	CCS
	LHLD	DMA	; get pointer to memory buffer */
	MVI	B,40H	; initialize loop counter for I/O */
			;transfers: 40 for 8" DD, 20 for 8" SD
	endif

	lda	dflag		; seek delay flag
	ori	rsec		; read sector command
	out	cmd		; issue..

	if 	Dysan
	mvi	a,sdma		; start transfer
	out	dma
	endif

	if	CCS
BREAD:	IN	DATA	; code to perform I/O transfer of  */
	MOV	M,A	; 	data to memory */
	INX	H
	IN	DATA
	MOV	M,A
	INX	H
	IN	DATA
	MOV	M,A
	INX	H
	IN	DATA
	MOV	M,A
	INX	H
	DCR	B	; decrement loop counter... */
	JNZ	BREAD
	endif

	call	comp		; transfer completed?
;
read2:
	xra	a		; clear seek delay
	sta	dflag
	in	stat		; good read?
	ora	a
	rz			; yes...
	dcr	e		; count off retries
	jnz	read1		; try again
	in	stat		; return status
	ora	a
	ret


**************************************
*** "WAIT FOR END OF DMA TRANSFER" ***
**************************************

comp:	
	call	delay		; before each check
	in	stat     	; Completed Transfer?
	rrc			
	rnc			; YES!
	jmp	comp		


********************************
*** "PROGRAM DISK CONTROLLER" ***
********************************

prg$dma:

	if	Dysan
	mvi	b,15		; Bytes Count 
	lxi	h,cmd$tbl	; Command Table
;
prg$dma1:
	mov	a,m		; load
	out	dma		; write to controller
	inx	h
	dcr	b		; -1
	jnz	prg$dma1
	endif

	if	CCS
	LXI	H,SECBUF	; store address of memory buffer */
	SHLD	DMA	; in pointer for disk controller */
	LDA	SELPT	; get drive select bits */
	OUT	DSEL	; sets autowait for 2422 controller... */
			; to ensure synchronization of I/O transfer
	endif

	ret

**************************************
*** "COMMAND TABLE DMA CONTROLLER" ***
**************************************

;	This data is used to program Zilog's
;	z80 DMA controller.

cmd$tbl:

	if	Dysan
 	db	0c3h		; Re-Set DMA Controller
	db	8bh		; Clear Block Counter
	db	79h		; Recieve Block 
	dw	secbuf		; Address To Store Block 
	dw	256 		; Block Size 
	db	14h		; Define Port (B) Address
	db	28h	 	; Define Port (A) Address
	db	85h		
	db	data   		; Data Reg FDC
	db	8ah		; Set DMA Controller Active HIGH
	db	0cfh
	db	3		; Data  ----> Memory
	db	0cfh
	endif


************************************
*** "CLEAR PENDING COMMANDS FDC" ***
************************************
;
;	Clears the floppy controller of any
;	pending commands.

clpend:
	mvi	a,clear		; clear FDC command
	out	cmd		; issue...

***************************************
*** "FDC DELAY TO PROCESS COMMANDS" ***
***************************************
;
;	This delay must be adjusted for different
;	clock speeds. 50 usec delay loop. 
;
;	Note:
;	     If altered, Ajust Index Timing Routine.

delay:				;  4.25
	mvi	a,fdelay	;  1.75
delay1:
	dcr	a		; 11.00
	jnz	delay1		; 27.50
	nop			;  1.00
	nop			;  1.00
	nop			;  1.00
	ret			;  2.50

********************************
*** "RADIAL TRANSLATE TABLE" *** 
********************************

;	Cursor Positioning table for radial
;	alignment test.

rad$neg:
	db	38	      	; 1  millinch
	db	36		; 2  "	  "
	db	34		; 3  "	  "
	db	32		; 4  "	  "
	db	30		; 5  "	  "
	db	28		; 6  "    "
	db	26		; 7  "	  "
	db	24		; 8  "    "
	db	22		; 9  "    "
	db	20		; 10 "    "
	db	17		; 11 "    "
	db	14		; 12 "    "
	db	11		; 13 "    "

rad$pos:
	db	40		; 1  millinch
	db	42		; 2  "     "
	db	44		; 3  "     "
	db	46		; 4  "     "
	db	48		; 5  "     "
	db	50		; 6  "     "
	db	52		; 7  "     "
	db	54		; 8  "     "
	db	56		; 9  "     "
	db	58		; 10 "     "
	db	61 		; 11 "     "
	db	64		; 12 "     "
	db      67		; 13 "     "

*********************************
*** "AZIMUTH TRANSLATE TABLE" *** 
*********************************

azi$tab:
	db	18		; head azmuith angle
	db	20		; +/- minutes
	db	22
	db	24
	db	26
	db	28
	db	30
	db	32
	db	34
	db	36
	db	38
	db	40
	db	42

**************************
*** "PROGRAM MESSAGES" *** 
**************************

me1:	

	if	Dysan
	db 	(-1) AND 0FFH,27,1,'Drive Diagnostic Program'
	db      (-1) AND 0FFH,31,2,'CP/M 80  Ver 1.0'
	db      (-1) AND 0FFH,23,4,'( Dysan Corp.   Santa Clara, Ca. )'
	endif

	db 	(-1) AND 0FFH,18,5,'<*>======================================<*>'
	db   	(-1) AND 0FFH,18,6,'<*>        DIAGNOSTIC COMMAND MENU       <*>'
	db      (-1) AND 0FFH,18,7,'<*>======================================<*>'
	db      (-1) AND 0FFH,18,8,'<*>                                      <*>'
	db      (-1) AND 0FFH,18,9,'<*>   R = Radial      H = Hysteresis     <*>'
	db     (-1) AND 0FFH,18,10,'<*>                                      <*>'
	db     (-1) AND 0FFH,18,11,'<*>   A = Azimuth     I = Index Timing   <*>'
	db     (-1) AND 0FFH,18,12,'<*>                                      <*>'
	db     (-1) AND 0FFH,18,13,'<*>   C = Centering   S = Spindle Speed  <*>'
	db     (-1) AND 0FFH,18,14,'<*>                                      <*>'
	db     (-1) AND 0FFH,18,15,'<*>   D = Drive Sel   E = Exit Program   <*>'
	db     (-1) AND 0FFH,18,16,'<*>                                      <*>'
	db     (-1) AND 0FFH,18,17,'<*><*><*<*><*><*><*><*><*><*><*><*><*><*><*>' 
	db     (-1) AND 0FFH,18,19,'SELECTION? ....',bs,0

me2:	db	'FATAL READ ERROR      ',0
me3:	db	'RE-CLAMP DISKETTE ....',bs,0
me4:	db	'CENTERING OK ....     ',bs,0
me5:	db	'  Minutes            ',0
me6:	db	(-1) AND 0FFH,25,2,'<>==========================<>'
	db	(-1) AND 0FFH,25,3,'<>       TRACK OFFSET       <>'
	db	(-1) AND 0FFH,25,4,'<>==========================<>'
	db      (-1) AND 0FFH,25,5,'<>                          <>'
	db	(-1) AND 0FFH,25,6,'<>       0   ---> 76        <>'
	db	(-1) AND 0FFH,25,7,'<>                          <>'
	db      (-1) AND 0FFH,25,8,'<>==========================<>'
	db      (-1) AND 0FFH,25,9,'<>   <ESC>  Cancels Test    <>'
	db     (-1) AND 0FFH,25,10,'<>==========================<>'
	db     (-1) AND 0FFH,25,12,'OFFSET? ...',bs,0


me7:	db	(-1) AND 0FFH,25,2,'<>==========================<>'
	db	(-1) AND 0FFH,25,3,'<>     TRACK SELECTION      <>'
	db	(-1) AND 0FFH,25,4,'<>==========================<>'
	db	(-1) AND 0FFH,25,5,'<>                          <>'
	db	(-1) AND 0FFH,25,6,'<>   A = (0)      D = (41)  <>'
	db	(-1) AND 0FFH,25,7,'<>                          <>'
	db     (-1) AND 0FFH,25, 8,'<>   B = (3)      E = (70)  <>'
	db     (-1) AND 0FFH,25, 9,'<>                          <>'
	db     (-1) AND 0FFH,25,10,'<>   C = (38)     F = (73)  <>'
	db     (-1) AND 0FFH,25,11,'<>                          <>'
	db     (-1) AND 0FFH,25,12,'<>==========================<>'
	db     (-1) AND 0FFH,25,13,'<>    <ESC> Cancels Test    <>'
	db     (-1) AND 0FFH,25,14,'<>==========================<>'
	db     (-1) AND 0FFH,25,16,'TRACK? ...',bs,0

me8:	db	(-1) AND 0FFH,24,5,'---  RADIAL ALIGNMENT CHECK ---'
	db	(-1) AND 0FFH,10,9,'Away',(-1) AND 0FFH,36,9,'Spindle',(-1) AND 0FFH,63,9,'Toward'
	db	(-1) AND 0FFH,10,10,'13 12 11 10 9 8 7 6 5 4 3 2 1'
	db	        '-1 2 3 4 5 6 7 8 9 10 11 12 13',0

me9:	db	(-1) AND 0FFH,25,2,'<>==========================<>'
	db	(-1) AND 0FFH,25,3,'<>      TRACK SELECTION     <>'
	db	(-1) AND 0FFH,25,4,'<>==========================<>'
	db      (-1) AND 0FFH,25,5,'<>                          <>'
	db      (-1) AND 0FFH,25,6,'<>    A = (35)   B = (44)   <>'
	db      (-1) AND 0FFH,25,7,'<>                          <>'
	db      (-1) AND 0FFH,25,8,'<>          C = (47)        <>'
	db      (-1) AND 0FFH,25,9,'<>                          <>'
	db     (-1) AND 0FFH,25,10,'<>==========================<>'
	db     (-1) AND 0FFH,25,11,'<>   <ESC>  Cancels Test    <>'
	db     (-1) AND 0FFH,25,12,'<>==========================<>'
	db     (-1) AND 0FFH,25,14,'TRACK? ...',bs,0

me10:	db	(-1) AND 0FFH,23,5,'---  DISKETTE CENTERING CHECK ---',0

me11:	db	(-1) AND 0FFH,23,14,'Press <SPACE BAR> For New Track',0

me12:	db	(-1) AND 0FFH,24,5,'--- AZIMUTH ALIGNMENT CHECK ---'  
	db	(-1) AND 0FFH,25,14,'<ESC> Will Cancel AZIMUTH Check',0

me13:	db	(-1) AND 0FFH,25,2,'<>==========================<>'
	db      (-1) AND 0FFH,25,3,'<>      TRACK SELECTION     <>'
	db      (-1) AND 0FFH,25,4,'<>==========================<>'
	db	(-1) AND 0FFH,25,5,'<>                          <>'
	db      (-1) AND 0FFH,25,6,'<>    A = (0)    B = (76)   <>'
	db      (-1) AND 0FFH,25,7,'<>                          <>'
	db      (-1) AND 0FFH,25,8,'<>==========================<>'
	db      (-1) AND 0FFH,25,9,'<>    <ESC> Cancels Test    <>'
	db     (-1) AND 0FFH,25,10,'<>==========================<>'
	db     (-1) AND 0FFH,25,12,'TRACK? ...',bs,0 

me14:	db	(-1) AND 0FFH,28,5,'--- HYSTERESIS CHECK ---',0

me15: 	db	(-1) AND 0FFH,15,8,'##################################################'
	db     (-1) AND 0FFH,15,12,'##################################################',0

me16:	db	'Positioner Hysteresis = ',0
me17:	db	(-1) AND 0FFH,25,5,'--- INDEX TO DATA TIME ---',0
me18:	db	'Index To ID In Usecs = ',0
me19:	db	(-1) AND 0FFH,27,5,'--- SPINDLE SPEED CHECK ---'  
	db	(-1) AND 0FFH,25,14,'<ESC>  Will Cancel RPM Check',0

me20:	db	'  Milliseconds',0
me21:	db	'  RPM',0

BLANKS:	DB	'                                        '
	DB	'                ',0
		                                                   
SELMSG:	DB	(-1) AND 0FFH,15,12,'WHICH DRIVE HAS THE DDD - A,B,C,D ?'
	DB	(-1) AND 0FFH,25,14,'SELECTION ? ....',0
		                                         

*************************
*** "POSITION CURSOR" ***
*************************

set$cur	db	0ffh
column	ds	1		; set column
row	ds	1		; set row
	db	0		; terminator

***********************************
*** "PROGRAM VARIABLE STORAGE" ***
***********************************

temp	ds	2		; temp storage 
diff 	ds	1		;  1st - 2nd read
ctrk	ds	1		; current track
savtrk	ds	1		; temp storage Hysteresis test
dflag	ds	1		; seek delay flag
point	ds	2		; table pointer
xpoint	ds	2		; table pointer positive
ypoint	ds	2		; table pointer negative
xoff	ds	1		; positive offset
yoff	ds	1		; negative offset
bais	ds	1		; bais from test track (Hysteresis)
hyerr	ds	1		; hysteresis error on first reading
SELPT	DS	1	;STORES BYTE FOR DISC CONTROL PORT

;
;	Storage area for 16/24 bit divide routine
;
msb	ds	1
msb1	ds	2
msb2	ds	2

inbuf:	db	3		;"max" byte for BDOS 10
incnt	ds	1		;"cnt" buffer for BDOS 10
buffer	ds	4		; console input buffer
secbuf	ds	256		; sector buffer

	ds	100		; stack space
stack	equ	$		; top down...
!E!O!F!