I have been looking more at the programmable IO (PIO) on the Raspberry Pi Pico and this definitely looks like it is going to work. I have been giving a lot of thought on how best to write the PIO programs. I thought some others might find the topic interesting/useful. The Pico has a total of 8 PIO state machines and they are arranged like this:
Code:
<--- FIFO <---
ARM CPU PIO STATE MACHINE <---> OUTSIDE WORLD
---> FIFO --->
On both XTA and the IBM drives, one of the ports (and the DMA) performs contiguous reads/writes into a memory buffer. The FIFOs seem to be perfect for this. It is even possible to DMA from the Pico RAM to/from the FIFOs, making it possible to implement the entire 512 byte memory buffer without any demand on a Pico CPU.
The writes from the PC to other ports also look to be pretty easy. The drive implementation does not need to respond quickly to these except to latch a "busy" flag. I think any hardware device with a microcontroller in the mix must be the same (Sound Blaster DSP for example). So a second state machine can send the port address and data values into a FIFO and a Pico CPU can pull those out and process them at its leisure. The busy flag is a bit tricky - the state machines can't do much in the way of math on register values. However I think there is a way to use duplicate code paths, one that explicitly sets an output pin high, and another that sets the same output pin low.
The remaining two read ports are a little tricky. In all cases they hold status/flags values. The FIFOs are not super ideal for setting these - we want the value read by the PC to update immediately, not provide a history of the port values. The state machines do have effectively 3 registers to hold values (two temp registers and the last value off the FIFO) so in principle one state machine could service reads for 3 ports. However there is no way for a Pico CPU to get a value into the temp registers without pausing the state machine and then it would be unable to respond to reads from the PC. The easiest approach is probably to use an entire state machine per read port and have the state machine constantly pull the FIFO so the data stays up to date.
Someone I was talking to privately asked about performance of the state machines. There seems to be oodles of performance. By my reading of the ISA bus documentation I have looked at, the Pico would have two whole ISA bus cycles to perform its response to ~IOR or ~IOW going low. All PICO state machine instructions execute in one cycle. For ISA at 10MHz and a Pico at 125MHz, that would be 25 PIO state machine instructions. Even allowing a cycle for latency and some more for headroom, that seems like it will be at least twice what is needed. Sometimes the the instructions can even perform two operations using side channel functionally. For example, one instruction could set the direction on an externa bus transceiver
and pull data from the FIFO. Even branches are always one cycle - none of the usual branch prediction, penalties if the branch is taken/not taken etc. It would be possible for example to use 4 branches to decode an entire 16 port range and only burn 4 cycles.
I did also figure out that the Pico could decode ISA IO addresses directly. One state machine can decode the address range and trigger other state machine(s) to handle the read/write. I think it might even be possible to implement an entire Sound Blaster Pro 2 on a Pico, sans DAC and 5v level shifting. Hard to be sure - there are 6 read registers on the SB Pro 2 and the complexity might burn a lot of instructions. That is a potentially tight limitation with PIO: only 32 instructions per 4 state machines.
Time to write some code. I do have a Pico up and running on a breadboard with a new hello-world project. Setting up the C++ SDK was more involved than Arduino but it and the documentation feel like professional tools to me. Better actually - all the source code is present too. It was still easier to set up than I have found other CMake projects to be. Great docs and a community build Windows setup tool very much helped. The Pico also seems well suited to field-upgrading firmware. It just needs to be connected to a computer via a micro-USB cable. It then shows up as a drive and the new firmware uf2 file is dragged over. I am sure it would also be possible to implement some kind of upgrade path using the vintage host PC but it is very nice to not have to implement something out of the gate.