Today I have been working on implementing enough of the F011 floppy controller to make the internal DOS work.
The idea is that it will point to a portion of the SD card storage corresponding with a 1581 image.
The floppy controller is reasonably well described in the C65 specifications manual, so a while back I set about implementing most of the registers.
The more recent work has focussed on tying those registers to the existing sd card controller.
First, I added some registers to select the starting sector on the SD card for the 1581 image, and some flags to tell the FDC whether it thinks it has a disk inserted, and whether it is write-protected. I already knew that the C65 startup checks the disk inserted bit when it decides whether or not to try booting from the floppy drive.
I also implemented an on-screen-display facility for the drive led, so that a square of pixels in the top left of the video display go red if the FDC is active, or blink red if an error has occurred. This was fairly simple, because the FDC has dedicated LED control bits used by the C65 ROM to turn the drive led on or make it blink, with the same indications as a 1541 disk drive. This works differently to a real 1581 where the LED interpretation is different.
Here you can see the drive led on-screen display as I cycle it through error indication, on solid for activity, and off a couple of times:
This got me to the point where I could lie to the C65 by making the FDC indicate a disk was present, and see what it did.
It turns out it went into an infinite loop. Some digging revealed that it was trying to step the head to track 0, and the track0 indicator bit was not being set. That's not surprising, since I hadn't implemented it. Here is the relevant bit of code from the C65 ROM. It uses LSR $D082 to push the TRACK0 flag into the processor's carry flag as an easy way to test the status of this flag:
9B85 A9 10 LDA #$10
9B87 4E 82 D0 LSR $D082 ; put bit 0 (TRACK0 flag) of $D082 into C flag
9B8A B0 05 BCS $9B91
9B8C 20 91 9A JSR $9A91 ; Execute FDC command from A, and wait for completion.
9B8F 80 F6 BRA $9B87
9B91 A9 00 LDA #$00
9B93 9D 0F 01 STA $010F,X
9B96 18 CLC
9B97 60 RTS
Once that was fixed, it got a bit further, but hit another infinite loop when a sector read succeeded, because the RDREQ bit was not being set to indicate that the sector was successfully read. Here is the routine. Basically the ROM checks if the RNF (sector not found) or RDREQ (sector found and read) flags are asserted, and loops otherwise:
; Read a sector?
975B 20 2C 9A JSR $9A2C ; Set FDC track, sector and side register from $1FB4?
975E B3 12 01 BCS $9872
9761 A9 40 LDA #$40 ; command byte: read sector from disk.
9763 8D 81 D0 STA $D081 ; FDC Command register
9766 AD 82 D0 LDA $D082 ; FDC Status byte 1
9769 29 10 AND #$10
976B D0 28 BNE $9795 ; Take branch and abort if RNF (read not found) bit set
976D AD 83 D0 LDA $D083 ; FDC Status byte 2
9770 10 F4 BPL $9766 ; Take branch and keep waiting if sector not yet found (RDREQ bit clear)
This is the sort of thing that comes up when specifications for a system are only mostly incomplete: integration testing is needed to discover and resolve the remaining ambiguities.
What is nice is that the drive light stays on on the screen, so that is working.
I have updated the FDC/sd card controller behaviour to attempt to fix this, by not clearing the RDREQ line after the sector has been read. The FPGA code is rebuilding, so hopefully it will get a step further tomorrow. Of course, I still haven't implemented actually reading out the bytes of the sector when they are read, so there will still be more work to do even if this fix is successful.
And that is as far as I have got today.