What does an MPI do, and why does it have to be upgraded?
Back in the day, small computer systems addressed everything as RAM. Great theory, but silicon was expensive in the eighties and a random subset of 16 address lines can be many logic gates added to the cost of every expansion card. To support cheap external hardware, computers of the day would provide 'slot select' signals. The card could use that, plus a few low order address lines for it's internal registers, and job done.
Apple had 4 slots, which covered a reasonable amount of expansion. The CoCo only had one, unless you add an external device like the MPI.
There are two output signals denoting a preselected address range.
|CTS||$C000 - $FDFF||read only ROM software|
|SCS||$FF40 – $FF5F||read/write hardware|
The CoCo also accepts two related inputs from ‘the’ external device.
|CART||A valid external ROM is present, run it.|
|SLEN||Disable CoCo’s internal address decoding.|
For a single device, simply connect SCS to the chip select for your hardware, and/or CTS to the chip select for your ROM chip. To auto run your ROM on startup, tie CART to the E clock. This lashup will ‘ghost’, in other words that low order address pattern will be repeated throughout the select range.
This is fine for one device, but what happens when two 'standard' expansion cards are plugged in? They stomp on each other, of course. And that is where SLEN comes in. An external device can ask the SAM/GIME to kindly not put out the CTS and SCS signals. The full address is still present on A0-A15, but no shortcuts. The MPI also checks this signal, since it also deals in SCS and CTS and needs to know when to shut up. It does this job just fine on any model CoCo, nothing to see here.
But the ghosting problem hasn't gone away, it's just been relocated. First, we need to identify the CTS range $C000-$FDFF, which looks like this in binary:
where all possible values in the xx positions will fall inside the range and can be ignored. For decoding work we only have to consider a range of 8 bit numbers.
The end of SCS is more expensive, 12 significant bits to puzzle out FF40-FF5F. Why not cut one more bit off for expansion? On a CoCo One or Two, this area is not used... and so, the MPI stops decoding at A5 so the SCS or read/write range is:
|FF40||11111111||010xxxxx||Start of SCS|
|FF9F||11111111||100xxxxx||End of MPI range|
|FF7F||11111111||01101111||MPI slot select|
This a problem for CoCo3, which wants the FF9x range for the GIME. The original 'big' MPI were actively hostile, letting writes to $FF7x echo to the related address $FF9x. Luckily, the ‘big’ MPI have an easy fix, replace the socketed PAL chip.
Newer MPI are more subtle, they don’t echo writes themselves but do leave both active. This could have been a BFD, ASICs are not as easy to replace as PALs, even if there was a socket. But somebody spotted a workaround.
Address table bit 7 is only set when CTS is active, or we are in the no-no range &FF9x. So all we need to do is hijack the MPI’s internal select signal ‘ENBUS’ and disable it when CTS isn’t active and address bit 7 is high (one). As luck would have it, this hijacking can be done outside the ASIC chip with a simple trace cut.
This must be done inside the wonder world of active low signals. Logic gates compare the ones. Active low signals are not ones and cannot simply be OR’ed together. Instead of asking our original question ‘is CTS set or SLEN set or bit A7 = 0? you have to ask ‘is CTS not set and SLEN not set and bit A7 = not 0 ?
And then, a NAND gate flips the output to again be active low. So once a second input stage determines ENBUS is not set we can finally compare if ENBUS isn’t not set, CTS is not not active or SLEN is not not active or address A7 is not not zero. Resulting in an output ENBUS* signal with $FF9x chopped off that we can supply to the rest of the MPI on other side of the trace cut.