With the basic hardware of the Zolatron 64 6502-based homebrew computer working fine, I’ve been spending most of my time on the ROM software.
It turns out that writing an operating system in 6502 assembly code is harder than you might think. Well, anyway, it’s harder than I thought.
- Backplane: The current rev A.1 board is working fine. However, I have a rev A.2 on its way from JLCPCB. This doesn’t fix any problems, it just makes some improvements. It moves from being a two-layer board to a four-layer one. The power planes may help signal stability. And more of the signals are broken out as headers at the ends of the board. I couldn’t order the new board in the same fancy red as the current one (well, I could have, but it would have doubled the price) so this time I’ve gone for a gothic black.
- Main processor: The current board is already rev A.3. All previous faults and bodges have been fixed, so this doesn’t need updating. However, I might do one last spin just to tidy up traces, add a power LED and make very minor tweaks. But the bottom line is, it’s working.
- Serial board: As detailed in the previous post, the current A.1 board has issues that required bodge wires and bodged resistors. A rev A.2 is also on its way from China which fixes those, plus adds blinkenlight LEDs. That will be the end of the line for the 6551-based serial board.
- 6522 VIA board: The A.1 board is working fine. I have, however, ordered a rev A.2 board with some improvements, including extra signals broken out and HE-10 header sockets in addition to the basic header pins.
So, if you’re keeping score (I know I am), of the four boards, two worked perfectly first time, one needed a single revision and another required two revisions. I’ll take that as a win, given that these are the most complex things I’ve ever designed. I mean, there’s no reason why they should work at all.
With a functioning platform, my focus is now on software. And I’ve been having lots of fun crushing bugs.
The things is, with a machine like this, and working in 6502 assembler code, finding which part of your software is causing problems is a lot tougher when you can’t just pepper it with PRINT statements saying things like “Got this far!”.
Actually, I can do something like that. The Zolatron has output via LCD screen and serial, so I’ve used that method that to some extent. But it’s not nearly as easy as it is when you’re working in a high level language.
Many other programming practices carry over, though. For example, I worked on a process for generating error messages. The problem was, every instance where the process was used created the same error message. Which part of the code was causing it? The only way to find out was to disable each use of the process, one-by-one, until the error message went away. (In this case, I was getting an error message where no error existed.)
The debugging process hasn’t been helped by my rapidly advancing age. Here’s how it goes:
- Write some code on the Mac – either new stuff or debugging.
- Switch off the Zolatron and pull the EEPROM chip.
- Put the chip in the programmer. Assemble and write the code to the chip.
- Put the chip back in the Zolatron.
- Switch on the Zolatron.
- Go back to the Mac and click on the terminal window. Type commands for the Zolatron. Watch as things go wrong.
- Goto 1.
Seems straightforward, although it involves quite a lot of walking, as the Zolatron is currently not next to the Mac (I must fix that). The problem is, I’ll be part way through this loop and forget what stage I’m at. Did I actually burn the new code to the EEPROM? You’d be amazed at how often I forget step 5 – and sometimes step 4. Oh well…
So far, it implements just three commands:
- VERS prints the version string for the ROM code to the standard output.
- LM hhhh hhhh (list memory) takes two four-character hex adddresses and prints the contents of the memory locations in the range defined by them – eg, LM C000 C03F prints the first 64 bytes of the ROM code.
- LP hh (list page) takes a two-character hex byte and uses it as the high byte of a memory location. It then prints the contents of the 256 bytes (ie, one page) of memory starting at that address, so LP C0 prints the first page of the ROM code.
And that’s it! I have implemented some reasonable error-checking and a mechanism for error messages.
Next up, I plan to implement PEEK, POKE and JMP. Many of you will have guessed at their functions, but for the rest: PEEK hhhh will show the contents of a single byte of memory, at location hhhh. POKE hhhh hh will write the value hh to the byte at location hhhh – assuming it’s writeable. And JMP hhhh will move the program counter so that the next instruction executed is the one at hhhh (a very dangerous and yet enticing command).
But what then? What am I going to do with this machine?
You’d think that I would have thought of that earlier – maybe right at the beginning. But the whole purpose of this project was for me to learn the fundamentals of how computers work. I’ve largely achieved that, so everything from now on is just messing about – which is fine.
There are things I have no interest in doing – writing games (other than, maybe, text adventures) and implementing high-level languages such as Basic or Forth. I mean, I could accommodate EhBasic on this machine – but why? It doesn’t actually teach me much and I already have vintage or vintage-like machines on which I can enjoy eight-bit versions of programming languages.
I probably need to develop some form of filing system. I could try to implement something that uses SD or CF cards, or maybe even a full-blown IDE interface. Or perhaps software to download code from the Zolatron’s Raspberry Pi assistant (imp) via serial. I did something similar for my BBC Master.
My current thinking is to develop an entirely new protocol, using a 6522 VIA on the Zolatron connecting to eight GPIO pins on the Raspberry Pi (plus a couple more for flow control). That way I could just drop any code I develop into a folder on the Pi and pick it up with a single command from the Zolatron.
This solution is likely to be slow, inefficient and buggy. But it would be mine and I would have a lot of fun developing it, which is the point.
Finally, I’ve updated the current ROM code on my GitHub page. I’ve now moved to a system using three branches for the software:
- Unstable is the branch I’m working on right now. It will almost certainly contain bugs and incomplete features.
- Dev should be code that runs fine. Even if some features are not fully implemented, they shouldn’t actually crash.
- Main is intended to be a stable branch in which those features that are present are also complete. It’s likely to lag way behind the others.
To what degree I’ll be able to live up to these promises is another matter.
[UPDATE – later the same day]: PEEK, POKE and JMP are all now implemented. So that was easy. I’ve also implemented BRK, which resets the stack pointer and jumps to the start of the ROM code – ie, a reset or break.