Prototyping a simple communication system for Project:65. Connecting from a PC to and Arduino to a Commodore 64.
I recently wrote a couple of programs that connect a PC and a Commodore 64 with an Arduino doing the translation in the middle: The C64 talks to the Arduino with SPI (Serial Peripheral Interface), and the Arduino talks to the PC with its usual serial-over-USB. On the PC, a terminal program can send text to the C64 and receive a response. This may be one of those projects where the first question isn’t so much “how” as it is “why?”. It’s kind of a long story.
I’ve spent the last couple weeks talking about the hardware side of my Project:65 computer, but I’ve also been thinking about software. Not application software, yet, but just programs to test the system and make sure it’s working correctly. One thing’s for sure: while hooking LEDs up to the address lines is a cute trick, I’m going to need a better method of communication.
I decided early on that I’d use a WDC 65c22 VIA for my first attempts at input and output. The VIA – that’s “Versatile Interface Adapter” – is a modern version of the MOS Technology 6522 that was used in the Commodore Vic-20. It features a couple of 8-bit parallel ports, a shift register, and a couple of timers. It’s a predecessor to the 6526 CIA (“Complex Interface Adapter”) that was used in the Commodore 64.
Then I had to decide how I was going to use it. The classic thing to do with this sort of headless machine is to add an RS-232 serial port and hook it up to a dumb terminal. Of course, I don’t actually have any dumb terminals anymore, and my current PC doesn’t even have a serial port, though I do have a USB to serial adapter in a box somewhere. I think.
Poking around online, I decided maybe that wasn’t the best approach anyway. While everyone agrees that you can do serial output with a 6522, nobody seems to recommend it. Especially not anyone with Vic-20 telecommunications experience. It apparently requires pretty good interrupt-based code to get even modest speed out of that interface without dropping characters.
I decided instead to do something quick and dirty, and come up with a better solution using more sophisticated hardware once I knew I had a functioning system. The quickest and dirtiest thing I could come up with was SPI – the synchronous serial interface I’ve used in a variety of previous projects. I’d used SPI on the C64 to talk to an analog to digital converter. I figured I could use the same technique to talk to an Arduino, and then let the Arduino send information back and forth to my PC.
Even so, this was going to involve a lot more code than any of my trivial tests, and I quickly realized that I was going to have to get both the 6522 and the RAM in the Project:65 computer working to pull this off. With two untested hardware elements to worry about, I decided I needed a more stable platform to develop the software on. That led to this week’s project: getting a C64 to work as an SPI master, sending text back and forth to an Arduino SPI slave.
On the C64 side, I needed to keep things simple so that my code would be portable to Project:65. My earlier experiments with SPI used the C64 User Port, which is connected to one of two 6526 CIA chips. The CIA isn’t exactly the same as the VIA, but I was only going to be using one of the parallel ports, and those parts of the two chips are mostly the same. The register layout and the location of the chip in the computer’s memory map is also different. I haven’t even figured out all the details of Project:65’s memory map yet, but as long as I didn’t hardcode any addresses in my software I didn’t figure that would be a problem.
I started with my code for talking to the MCP3008 ADC, and modified it for text and two-way communication. I used a very primitive polling technique, where the C64 sends a character and receives one back simultaneously. Of course, a lot of the time those characters will be ASCII 0’s – the NUL character – which will be ignored on the receiving side. I also fixed up the timing of that code a little bit – in my original version, I was always receiving bits one clock cycle off from when I expected them. This video at Sparkfun.com helped clarify my understanding of the timing situation.
The logic on the C64 side looks something like this:
// send the current character and receive a new one
current_character = SendAndReceive (current_character);
if current_character is newline or carriage return
current_character = NUL
SendString ("\nYou said \"")
append current_character to character_buffer
So, for sake of testing, it does two things. The first is that it echoes most received characters back to the sender – useful if you expect the sender to be a terminal program. The second is that it stores the received characters in a buffer, and when it receives a newline it sends the whole buffer back with some explanatory text. I figured this would be a good way to both shake out the protocol and, when this eventually runs on Project:65, test if the memory is actually working like it’s supposed to.
The Arduino side was a little tricky. Remember, I was planning this with the C64 as the SPI master and the Arduino as a slave device – but the Arduino SPI library and its documentation is written to expect the Arduino to be the master. Google turned up these posts by Nick Gammon that explained how to set up the Arduino as an SPI slave.
The Arduino side is interrupt based, so that it can respond quickly to the SPI clock which is controlled by the C64. It simply uses a couple one-byte buffers to communicate with the non-interrupt-driven loop() part of the Arduino sketch, which sends and receives information from the PC using the Arduino’s serial library.
The resulting code is a little graceless – the C64 side does a lot of manual bit-banging and is probably terribly slow, while the Arduino code has some hopelessly kludgy buffer code that I got bored with before I got it working correctly – but the important thing is that the communication actually happens, as you can see in the screenshot. There are some occasional glitches when one or the other system is starting up – if I go anywhere with this longer term, I might need to add some more formal handshaking. I think I’ll worry about that when the need arises.
Terminal program on the PC. I can enter text here and have the C64 echo it back, or just echo what’s being typed on the C64’s keyboard.
One I got the code running, I decided to have a little fun with it. I changed the C64 side to accept input characters both from the SPI bus and from the C64’s keyboard – so I could type on the C64 and have my characters show up in the terminal window on the PC. That, of course, led me to thinking about PETSCII – Commodore’s slightly weird variation of ASCII. PETSCII dates back to the original Commodore PET, released in 1977. It originally featured capital letters and the special Commodore graphics characters – all those little figures on the sides of they keys on a C64.
The character set was later modified to include special characters that did things like change the text color. In C64 basic, strings can contain all of these special characters that you type with a variety of modifier keys. Of course, nobody but another C64 would understand them. Terminal software like PuTTY uses a different set of control characters – ANSI codes – which were commonly used on BBS systems back in the 80’s.
Just for fun – because I have no intention of doing this for Project:65 – I added some translation code to the Arduino software, to translate some of the PETSCII special characters into their ANSI equivalents. That’s how I got the multicolored text in the screenshot.
case 28: // red
case 5: // white
case 145: // cursor up
case 17: // cursor down
case 157: // cursor left
case 29: // cursor right
There’s a lot of work to be done before I can run this code on Project:65. I need to get the 6522 hooked up, as well as the RAM. And I need to finalize the memory map and devise the memory decoding logic that will control access to the VIA, RAM, and ROM. I’m just starting that process, and I think it’s going to be the most challenging part of the whole build.
I’ve put up the source code for both the Arduino and Commodore 64 sides of this project for those who are interested. It’s not exactly ready for prime time, but it gives an idea of the experimental process of late-night weekend computing projects like this.