Pretty much every computer needs persistent storage. And these days we’re spoiled for choice – everything from hard drives down to micro SD cards being capable of holding more information than I can comfortably imagine.
With clever interfaces, these options are also open to builders of homebrew computers, like the 6502-based Zolatron 64 (Z64). But it does mean grappling with various protocols and understanding file system structures, which is all good learning material. But it’s not discovery.
I’ve decided to roll my own persistent storage, taking advantage of the Raspberry Pi that’s already attached to the Zolatron. This Pi Zero 2 W is linked via a serial interface and is how I interact with the Zolatron. But a serial interface uses only two GPIO pins on the Pi, and it’s a shame to see all the others being wasted.
So here’s the plan. I’m going to use a 65C22 Versatile Interface Adapter (VIA) on the Z64 to talk to the Pi. The 65C22 has 16 I/O pins, much like the GPIO of the Pi. They are arranged in two ports. I’m using all eight pins of Port A as a parallel 8-bit data bus. And I’m using some (currently four) pins on Port B as control signals.
I’m not going to get fully into this solution here. For one thing, although working, it’s still a work in process. What I am going to talk about is the first issue I had to face, for which I thought I had a solution – but didn’t.
The 65C22 pins operate at 5V. The Raspberry Pi’s GPIO pins use 3.3V.
My immediate instinct was to make use of the handy TXB0108 chip. This is a bidirectional level shifter and I’ve employed it many times in the past (usually in the form of Adafruit’s handy breakout board) to deal with incompatible voltage levels.
But when I hooked up all the wires, and nothing was working, I started to get a sinking feeling. And, as always at this point, out came the oscilloscope.
Signals travelling from the 5V side to the 3.3V side were doing fine. High (logic 1) signals going the other way were also getting through okay. It’s when a pin on the 3.3V side needed to pull a signal to 0V that things were going quack-quack-oops. The signal level never got below around 2.5V.
The TXB0108 is known for being somewhat weak at driving lines – it’s inherent in its design. I suspected that something is pulling the lines high and the TXB0108 isn’t capable of overriding it. As we’ll see, that may have turned out to be true.
The control signals are not a problem because they travel in only one direction. I can directly connect signals going from the Pi to the Zolatron because the 65C22 will accept the 3.3V signals as valid highs. And for the (currently two) signals going from the 65C22 to the Pi, I’m using simple resistor-based voltage dividers (with 2.2KΩ and 3.3KΩ resistors).
It’s the data bus that’s a problem, because it needs to be bidirectional.
Divide and conquer
I asked over on 6502.org and got lots of good ideas. Someone pointed out that a resistor divider approach should work in both directions. But it didn’t. I still have the same problem of the Pi being unable to pull the line to 0V.
That drove me back to the datasheet for the 65C22. In particular, I wanted to look at different variants. I’d previously encountered a not-dissimilar problem which entailed the addition of a diode (
I’ll go into that some other time. EDIT: Actually, I already wrote about it here.).
What I found was interesting.
I had been using the ‘N’ version of the WDC65C22. Here’s the schematic for one of the I/O pins.
Now, imagine we’re using this as an input (which is our problem case). Reading from left to right, the DDR line will be 0, which is flipped to a 1 by the inverter. It doesn’t matter what the DATA line is doing. The output of the NAND gate will be 0, which goes to the gates of two MOSFETs.
The lower MOSFET is N-channel, where the transistor turns on when there is a positive voltage on the Gate relative to the Source (which, in this case is the lower connection, tied to GND). That’s not the case here, so the transistor is off.
The top MOSFET is a P-channel version. With this type, the transistor is turned on when there is a negative voltage on the Gate relative to the Source (here it’s the top-most connection). That is the case in this instance, so the transistor turns on and there will be 5V provided to the pin via the current-limiting resistor. It’s effectively a pullup resistor!
So there’s the root of my problem.
But let’s look at the ‘S’ version of the 65C22.
We still have the totem-pole MOSFETs, but with no power-limiting (or pullup) resistor. Also, the signal path is different. I’ll spare you the blow-by-blow, but the outcome is that, when DDR is 0 (input mode) both transistors are turned off.
I pulled out the 65C22N and replaced it with a 65C22S – still using the simple resistor-based voltage dividers – and lo! It worked!
The downside of this is that the PCB I’m planning will require 24 resistors for the 12 signals lines that need to have level shifting (including two spares).
Then I had a thought. (It happens occasionally.)
If my problem was to do with using the wrong version of the 65C22, could I go back to the TXB0108 level shifter chip? That would make life a lot simpler.
I rewired everything, switched on and … nope. Didn’t work. And a few minutes with the oscilloscope provided some evidence as to why this is. Some of the signals are quite brief, and I think the TXB0108 is just too slow.
I also tried out the TXU0104. This is from the same family of chips, but is unidirectional, which I thought might make it faster. But this had the same problem.
But never fear. I have another cunning plan involving a chip that’s new to me. First, I need to experiment with it, so check back soon.