This is the sixth part of a series of posts detailing steps required to get a simple Z80 based computer running, facilitated by a Teensy microcontroller. It’s a bit of fun, fuzing old and new hobbyist technologies. See Part 1, Part 2, Part 3, Part 4, and Part 5, if you’ve missed them.
Making TeensyZ80 run with a faster, asynchronous clock seems a simple change at first, but it’s proving tricky. The high level plan is:
- The Clock signal is provided by another source (arduino nano at present)
- The MREQ and IOREQ lines are used to latch the WAIT line of the Z80 to allow the Teensy to respond to the request.
- The Teensy senses the WAIT line, performs any actions, and then resets the latch to bring the WAIT line high again (it’s active low).
- The Z80 continues as normal.
So with some simple 74 series logic, the MREQ and IOREQ pins are NAND’d together, producing a rising signal edge if either Z80 output go active low. This is fed into a 74HC74 flip flop as it’s clock, with the data pin tied logic high. This allows us to connect the Z80 WAIT input to the notQ output. The clear pin of the d-type flip flop is connected to the Teensy so it can reset it and allow the WAIT line to return high, letting the Z80 continue.
I had the Teensy set up to perform an interrupt routine on a falling edge of WAIT. Sadly, this didn’t seem to work. In fact, I could not confirm the interrupt was being called at all. I’ll have to look into this in detail but using interrupts really is an optimization in this case, so I soldiered on.
I’ve had several problems with Teensy microcontrollers during these posts. I had two units, one has completely bricked, and the other is very unstable. It seems to be due to the fact that if Pin 33 is low and an input when a program is uploaded to the Arm then the Mini54 chip can fail in some way. The Mini54 chip controls the bootloading process of uploading new code, so it effectively bricks the device. It is an issue that should really be given more prominence as if there was an announcement stating pin33 should never be used in certain ways I’d have two fully working Teensy devices. But sadly, all the documentation still states it as a fully configurable digital pin capable of input and output.
End Teensy Rant
Instead of using an interrupt, to try to get something working I created a tight loop() function that didn’t do anything while WAIT was high. As soon as it detected a low signal, it would perform the actions required. I disabled Z80 mode-2 interrupts for now, and removed the I/O debounce code. A very simple example seemed to work – but it was still quite slow, despite an arduino nano driving a clock at around 200KHz which is faster than what the Teensy was providing when running in synchronous mode.
I tried a larger example, one which printed text to the console, and it was obvious something was not right – the output slowly became corrupted. However, there were signs of promise. I was able to input a 4MHz clock and things were failing/corrupting in a somewhat similar way. Still corrupt, but it was the same behavior.
The issue was that I failed to include the RD/WR lines from the Z80 in my latching circuit. You can see from the timing diagram that, especially in the write cases we need to WAIT when those are active too, not just MREQ or IOREQ.
I redesigned the latch circuit.
This worked a lot better! I could only use the I/O port which put characters to the screen, but it was running well – and my simple test program, which printed “Welcome to TeensyZ80!” in an infinite loop, was stable even at 1MHz. I’d love to break the MHz barrier for this, but given we’re still on a breadboard and I don’t have a scope capable of inspecting this to the detail some of the issues require, I may need to settle for much less. So this simple test at 1MHz is very encouraging. I tried clocking it at 1.5MHz, but some artifacts in the printing arose.
When implementing my serial, display and filesystem devices which are accessed as I/O reads/writes, I created a system which relied on implied state behind the scenes on the Teensy. To set the colour of the characters being printed to the screen, two writes to the same port would write high and low values. It’s even worse for the serial device, where you had to write command packets to the I/O ports followed by a variable amount of data. I think i’m going to need to redesign all of the previous work, to operate on separate ports. For example, there will be a ColourHi and colourLow port which together define the 16-bit colour of the console. It’s not much work, but is something I’d overlooked and will take time.
This is a very quick update to Teensy Z80 work, It’s still very much ongoing. I’m also working on another project involving the miniSpartan6+ FPGA board. That’s another bit of fun – who doesn’t want to design their own processor?
Let me know any thoughts, as always, via twitter @domipheus !