Example Program
.Z80
TITLE FDC TRACK READER
ASEG
ORG 100H
BDOS EQU 5 ; BDOS entry point
; Assumes FDC is at its standard I/O address
CMDREG EQU 192 ; Write: FDC Command register
STATREG EQU 192 ; Read: FDC Status register
TRAKREG EQU 193 ; FDC Track register
SECTREG EQU 194 ; FDC Sector register
DATAREG EQU 195 ; FDC Data register
LATCH EQU 200 ; FDC board control latch
START: LD HL,FIN ; program end
LD DE,6300 ; length of work space
CLEAR: LD A,0 ; Clears work space
LD (HL),A
INC HL
DEC DE
CP D
JR NZ,CLEAR
CP E
JR NZ,CLEAR
; Select 8-inch when performing all seeks so that 3ms step
; rate can be achieved
LD A,94
OUT (LATCH),A ; Select DO,SO,DDEN, No ints,8-inch
LD A,8
OUT (CMDREG),A ; 'Restore' head to track 0
CALL WAIT ; Wait for ready
LD A,80
OUT (DATAREG),A ; Load data register with 80
LD A,24
OUT (CMDREG),A ; Make it 'seek' track 80
CALL WAIT ; WAIT until FDC ready
LD A,8
OUT (CMDREG),A ; 'Restore' it to track 0 again
CALL WAIT
CALL READ ; Read the track data
JR PRINT ; and print it out.
; Subroutine to wait for FDC ready
WAIT: LD B,6
WAIT1: DJNZ WAIT1 ; Delay 12µs before status is valid
WAIT2: IN A,(STATREG)
AND 1
JR NZ,WAIT2 ; Wait until FDC is not busy
RET
READ: LD HL,FIN
LD C,DATAREG
READY: IN A,(STATREG) ; Loop until drive is ready
BIT 7,A
JR NZ,READY
; When reading or writing to a sector
; write the sector and track number to the
; respective registers at this point
LD A,30 ; Set to 3.5 or 5.25 drive
OUT (LATCH),A
LD A,228 ; Read track command
OUT (CMDREG),A ; Initiate track read
LD B,6
DEL: DJNZ DEL ; Short delay
LOOP: IN A,(STATREG) ; Get status
RRCA
RET NC ; return if finished (BUSY not set)
RRCA
JR NC,LOOP ; If no data request then loop
INI ; Read data to (HL) and inc HL
JR LOOP ; The timing of this loop is critical
; SAMPLE READ AND WRITE SECTOR ROUTINES
; Read a sector
; Call with A = xxxMxESx
; where: M = multiple sector flag
; E = 15ms delay flag
; S = side select flag
; This routine sets the remaining bits to a command
; compatible with all the WD279x series FDCs.
RDSEC: AND 8EH
OR 88H
LD C,DATAREG
OUT (CMDREG),A
LD B,6
RDEL: DJNZ RDEL
RLOOP: IN A,(STATREG) ; Get status
RRCA
RET NC ; return if finished
RRCA
JR NC,RLOOP ; If no data request then loop
INI ; Read data to (HL) and inc HL
JR RLOOP ; The timing of this loop is critical
; write a sector
; call with A = xxxMxESx
; where: M = multiple sector flag
; E = 15ms delay flag
; s = side select flag
; This routine sets the remaining bits to a command
; compatible with all the WD279x series FDCs.
WRSEC: AND 8EH
OR 0A8H
LD C,DATAREG
OUT (CMDREG),A
LD B,6
WDEL: DJNZ WDEL
WLOOP: IN A,(STATREG) ; Get status
RRCA
RET NC ; return if finished (busy not set)
RRCA
JR NC,WLOOP ; If no data request then loop
OUTI ; Write data from (HL) and inc (HL)
JR WLOOP ; The timing of this loop is critical
; END OF ROUTINES
PRINT: LD DE,6293 ; The code from here onwards
LD HL,FIN ; displays the read data (and
NEXT: LD A,(HL) ; address markers etc.) from
RRA ; memory in hex. on the screen.
RRA
RRA
RRA
AND 15
LD BC,TABLE
PUSH HL
PUSH DE
LD H,0
LD L,A
ADD HL, BC
LD E,(HL)
LD C,2
CALL 5
POP DE
POP HL
LD A,(HL)
AND 15
LD BC,TABLE
PUSH HL
PUSH DE
LD H,0
LD L,A
ADD HL,BC
LD E,(HL)
LD C,2
CALL BDOS
LD E,' '
LD C,2
CALL BDOS
LD E,' '
LD C,2
CALL BDOS
POP DE
POP HL
INC HL
DEC DE
LD A,D
CP 0
JR NZ,NEXT
LD A,E
CP 0
JR NZ,NEXT
RET
TABLE: DB '0123456789ABCDEF'
FIN:
END
Macros:
Symbols:
BDOS 0005 CLEAR 0106 CMDREG 00C0 DATARE 00C3
DEL 0153 FIN 01EB LATCH 00C8 LOOP 0155
NEXT 0194 PRINT 018E RDEL 016A RDSEC 0160
READ 013E READY 0143 RLQOP 016C SECTRE 00C2
START 0100 STATRE 00C0 TABLE 01DB TRAKRE 00C1
WAIT 0133 WAIT1 0135 WAIT2 0137 WDEL 0181
WLOOP 0183 WRSEC 0177
No Fatal error(s)