The WD177x is a family of chips produced by Western Design Center. They are relatively common in Thomson machines and elsewhere. ====== Registers ====== The floppy controller has 4 registers. The programming is done in several phases: * Setup phase: configure the settings (track, sector, etc) * Command phase: write a command to the command register * Data phase (only for some commands): get or send data to the floppy controller. Thomson machines don't connect the floppy controller interrupt to the CPU in any way, so all the communication must be done by polling the FDC. This may be tricky to get right. ^TO Address^MO Address^Name^Description^ |E7D0 |A7D0 |STR/CMDR|Command (write) and Status (read)| |E7D1 |A7D1 |TKR |Track| |E7D2 |A7D2 |SECT|Sector| |E7D3 |A7D3 |DR |Data| |E7D8 |A7D8 |Extension control| the "Extension control" register is not part of the floppy controller, but is an extra latch in Thomson floppy extension design. It has the following functions: * Bit 0: side select * Bit 1: drive select 0 * Bit 2: drive select 1 * Bit 7: single density mode ====== Programming samples ====== All these code snippets assume X points to the floppy controller base address (E7D0 or A7D0). ===== Waiting for the controller ===== As the floppy drive is slow, you have to wait for it after sending a command. Here is how to wait for the "ready" bit in the status register. wready LDA ,X BITA #$1 BNE wready ===== Seeking to a track ===== The Track register is not used directly as you might expect. It is used internally by the FDC to keep track of the current track (!), so writing to it would get everything out of sync. Instead, you do this (assuming A register holds the track number to seek to): seek STA 3,X ; Load track number in the DATA register LDA #$10 ; SEEK command STA ,X ; ... to the command register For this to work, the TRACK register must be properly initialised. It should hold the current track number. If you don't know the head position, a RESTORE command may be used to reset the head to track 0. ===== Realigning the drive head ===== This moves the head to the outside of the disk until the TRK0 signal from the drive is raised. At this point, the head position is known (it's on track 0), so the TRACK register is reset to 0. You can then seek somewhere else. restore CLRA STA ,X ; Command 0 is RESTORE ===== Reading a sector ===== U points to the destination buffer, D holds the track number and sector ID. This assumes the Side register was set properly, and the head sent to the right track (the track value in D is used only to match with the on-disk sector ID). read STD 1,X ; Stores both the track and sector in appropriate registers LDB #$88 ; Turn motor on and read STB ,X BSR delay ; Wait for the command to be processed rloop LDB ,X ; Read status register BITB #$2 BEQ done ; The FDC isn't ready to send the next byte yet LDA 3,X ; Get next byte STA ,U+ ; Store it in buffer BRA rloop done BITB #$1 ; Is the command done? BNE rloop ; If not, try again and see if the next byte is now available RTS delay BSR hop ; Just waste 35 cycles jumping around BSR hop BSR hop BSR hop BSR hop RTS ===== Writing a sector ===== Input: U points to the data to write, D holds track number and sector ID. write ORCC #$50 ; Disable interrupts, our timing is critical STD 1,X ; Load track and sector IDs LEAY 3,X ; Point Y to the data register LDA #$A8 ; Spin up motor and write STA ,X BSR delay ; Wait for spinup BRA do load STA ,Y ; Write one byte do LDA ,U+ ; Get next byte wai LDB ,X ; Read status register BITB #2 ; Is the FDC waiting for one byte? BNE load ; If so, send it one BITB #1 ; If not, is it busy, or is it done? BNE wai ; It's busy, wait a little... ANDCC #$AF ; Restore interrupts, we're done with the timing critical stuff RTS