Apple disk controllers (was: Sharp MZ-80B boot disk

From: Eric Smith <eric_at_brouhaha.com>
Date: Fri Dec 20 12:09:02 2002

> seeing one that had some extra diagnostics and stuff. And, of
> course, there was the Sorrento Valley Associates board that did MFM
> in Apple][

Sellam Ismail wrote:
> Ooh, juicy! Where can I get one of those?

Fred Cisin wrote:
> It's been a while since I've seen one. They were mostly pushed in the
> 80s for being able to connect 8" drives!

As far as I know, they ONLY worked with 8-inch drives. The one I used
only did FM (single density). It's perhaps possible that they might have
later offered an MFM (double density) version, although such a controller
would have been rather more complicated. On an 8-inch MFM disk, you
only get a nominal 16 microseconds per byte transferred, and the reality
is that you have to be prepared to handle a byte every 13 microseconds.
An Apple ][ can't do that via programmed I/O, so you'd either have to
have DMA, or do some tricks.

The 8-inch MFM controller I designed for the TLB computer (another 1 MHz
6502 system) used "tricks". The basic idea was that the 6502 code would
look like:

        clc
loop: lda fdc_data ; 4 read a byte from the FDC
        sta buffer,x ; 4 store it to memory
        inx ; 2 advance pointer
        bcc loop ; 3 branch always

Note that the loop takes exactly 13 cycles. You might ask, "But Eric,
what if the FDC doesn't have data ready when the lda instruction is
executed?" The FDC was wired to drive the 6502 RDY line (low?) if a
read occurred when the data wasn't yet ready. And you might ask how
the processor gets out of the loop. That's done by the completion
interrupt. The completion interrupt checks the stacked PC, and if the
interrupt happened during that loop, changes the stacked PC to the
address of the code that cleans up.

In order to support reading to a buffer anywhere in memory, the code
modified the absolute address in the "sta buffer,x" instruction.
Alternatively, an indirect indexed address mode like "sta (ptr),y"
could have been used, but it would have taken one cycle longer,
which wouldn't have met the required minimum loop time.

Note that the buffer was not allowed to cross a page (256-byte)
boundary, because that also would add a cycle to the sta instruction
timing.

The write code was similar:

        clc
wrloop: lda buffer,x ; 4 read a byte from memory
        sta fdc_data ; 4 write to FDC
        inx ; 2 advance pointer
        bcc wrloop ; 3 branch always

But this was even more tricky, because the NMOS 6502 doesn't allow the
RDY line to stretch a write cycle. [*] For writing, instead of
using RDY on the access to the fdc_data register, the card decoded
the address of the opcode of the sta instruction of that loop, and
drove RDY when that opcode was fetched if the FDC wasn't ready to
accept another byte. This meant that the sta instruction had to be
at a predetermined address, which was accomplished by putting it in
an EPROM.

The card had a flip-flop to enable the RDY logic, so that if the
system wasn't trying to access the floppy but there was a stray read
of the FDC data register [**], the system wouldn't hang.

The cards for a TLB computer are fairly large. I didn't think I could
cram all the logic onto a standard-sized Apple ][ card back in 1981,
although there would have been a better chance with this scheme than
with DMA.

Eric


[*] Contrary to popular belief, this was NOT a bug in the processor.
It was done quite deliberately. Back in 1975 when the 6502 was
designed, there were plenty of RAMs that could meet the 2 MHz 6502
timing for read and write cycles, but most ROMs (including PROMs and
EPROMs) could not. Since you don't ever write to ROMs, they only
needed to support stretching the read cycles.

Years later, the 65C02 family added the ability to stretch write cycles.


[**] The NMOS 6502 would generate a "dummy read" cycle if you used an
indexed address mode and a page boundary was crossed. This was especially
common on the Apple ][, where accessing the resources on a peripheral
card was usually done by indexed addressing, with 16*slot in the index
register. The dummy read occurs at an address 256 bytes lower than the
desired address, because the carry hasn't yet propogated. This was
fixed in the later CMOS parts.
Received on Fri Dec 20 2002 - 12:09:02 GMT

This archive was generated by hypermail 2.3.0 : Fri Oct 10 2014 - 23:34:41 BST