• Hello, Guest! Welcome back, and be sure to check out this post for more info about the recent service interruption and migration.

The TashProject That Wasn't


Well-known member
tl;dr: Tashtari tries to make a floppy drive emulator in a single 8-bit PIC, doesn't succeed.

Honestly, TashTwenty really surprised me in how well it worked. Between the unknowns of the half-documented DCD protocol and the limitations of the 8-bit PICs that I so love, I wasn't at all sure going in that I was going to be able to manage it. The fact that I did was sufficiently confidence-inspiring that I thought, why not a floppy drive emulator? After all, I'd already proven that a PIC conversing over the IWM/phase-line interface was possible and this was just another form of that. ...Wasn't it?


My ambitions were, if not modest, at least tempered. Its user interface would be the bare minimum required to be functional, speed would not be a priority, and above all, it would only emulate GCR (400/800KB) disks, no support for MFM required for 1.44MB disks. MFM has lots of strange rules about where it places its bits - fine if one has programmable logic in one's arsenal, but I knew that if I was bitbanging it with a PIC, there would be no chance of it having any time to do anything else. At least I knew the IWM was a shift register at heart, and GCR would be manageable.


In TashTwenty, I'd already made a PIC respond fast enough to the IWM's phase lines to satisfy the Mac, so I was confident I'd be able to do so again. I'd done this by letting the PIC's lone interrupt vector be completely owned by the interrupt-on-change interrupt and writing extremely tight code to determine the current state of the phase lines and set the read line accordingly. The added wrinkle in emulating a floppy drive was that the Mac can choose at any time to move the phase lines to select the read head and it may or may not be expecting the drive to serve up data from the current head and track - no way to know, so the emulated drive has to have the data ready to stream at any time. Again, easy to do with programmable logic, but both the mainline and interrupt code are accessing the same GPIO signal that determines the state of the read line. How to allow the mainline to do the split-second timing it needs while still allowing the interrupt handler to shift to a different "register" as soon as the Mac demands it?

This I did by having two copies of the mainline code: one "active" one where the mainline would be able to set the read line whenever it desired, and one "inactive" one, identical, except that all the instructions that changed the read line were overstruck with no-ops. The interrupt handler can jump in at any point and switch from one mainline to the exact same place in the other, in effect allowing the mainline to independently emulate a spinning disk while the interrupt handler connects and disconnects it to/from the output pin as necessary. This, I was sure, was the hard problem solved.

Nope. Turns out, the Mac floppy driver is really impatient. When the IWM is speaking DCD, the Mac knows it's talking to an intelligent device and permits it some time to do its thing and write or retrieve the requested data. When it's hooked up to a floppy drive, it wants what it wants and it wants it right now, and if it doesn't get it, it raises a disk error. There are some ways in which one has limited ability to stall it, but there's no guarantee that the myriad different Mac ROMs out there have the same ones, so I'm reluctant to press them too hard.

Reads still look doable. Start the SD card doing its thing while sending the address mark, it should have its data ready to clock out when it's time to send the data mark. Writes, though, are another story. Receiving the data coming out of the IWM takes 100% of the PIC's time, and once that's done, it needs to be decoded. Not only this, but it needs to be decoded twice: once to convert the 7-bit IWM bytes into 6-bit "nybbles" and assemble each quartet of them into three 8-bit bytes, and once to un-mangle the bytes from the brain-damaged checksum algorithm that GCR disks use, both computationally-intensive on a PIC. One can potentially do a little stalling for time while sending the address mark, but doing these things at the same time is just too much to ask. Maybe with a long enough unrolled loop it'd be possible, but that'd be a really big loop, and I've already halved my memory space with the active/inactive mainline.


I decided at this point that what was feasible no longer represented a desirable result: a floppy drive emulator that could only emulate read-only 400/800KB floppies and had a user interface only a software engineer could love? Not particularly exciting, no.

What I ended up with is a piece of firmware that acts as an IWM-to-UART bridge. With a device connected to its UART that can respond to its rapid and changing demands for this or that track/head's data (already encoded, please) and sudden emissions of data to be saved to permanent storage, it should be able to take care of the task of interfacing to the IWM. I say "should" because I don't have such a device. I tried writing one on the PC with the idea of it being an image "server" of sorts, but it turns out that there's a leisurely 16-millisecond pause between the chip demanding data and the PC serving it up. Too slow.

I think it's a decent outcome considering the circumstances, but I'm not quite proud enough of it to call it the Integrated Tashtari Machine. =)

Postscript: Thanks to @cheesestraws for writing me a little test application to cough up the error code from the Sony driver! Without it, I'd probably still be wheel-spinning.
Last edited: