Many of the projects I take on aren't necessarily practical or done in the most efficient way. I often approach projects in a way that forces me to learn new concepts and/or technology. The project below may be a combination of practical and "why would you do that?".
After watching Ben's SPI video, I had implemented SPI to work with a BME280 sensor and an 8-character, 7-segment LCD display using a MAX7219. This was a good start to SPI for me, but I wanted to eventually connect my 6502 to an Arduino via SPI, opening the door to all kinds of expansion options. My primary goal of the project was to get SPI communication working between my 6502 and an Arduino. My secondary goal was to get some more experience with shift registers.
Design Overview
I used a '589 to shift 8-bit data from the VIA to the Arduino Nano via SPI. The Nano communicates to the PC via serial (through the USB connection). Return communication comes in as SPI on the '595 and back to 8-bit for the VIA. As far as a "protocol" on top of SPI, the Arduino expects a one-byte instruction followed by one or more bytes of data. The Arduino can return one or more bytes of data. I started building an instruction table like I have seen with other SPI devices.
In the video, I demonstrate the printScreen instruction. I had three sets of code to manage:
6502 assembly code - Support for the 'Print' keyboard scancode. When pressed, send the SPI 003 printScreen command to the Arduino. Read the contents of video RAM and send each byte (containing the pixel color information) to the Arduino.
As I write this, the latest version of my 6502 ROM code is available here.
Currently, I have some delays built into the 6502 code to help the poor Nano breath (the Nano is doing serial communication with the PC). The SPI implementation in my 6502 is capable of running faster.
Arduino C++ code - Receive the SPI command and process the incoming video RAM data. This is interrupt driven. Write the data to the serial connection to the PC.
Windows forms C# code - Receive the raw pixel data via serial (again, interrupt driven). Convert the 6-bit color palette to a 24-bit color palette. Draw the pixels on the Windows form.
While I have the general framework built to show a proof of concept, I have some work to do to clean up the code and track down a couple of bugs.
The Value of An Oscilloscope
This was a great exercise to learn the SPI trigger and decode functions of my oscilloscope. I found the list view (at the bottom of the screen shots below) to be extremely helpful. Trying to implement an SPI solution without a four-channel oscilloscope (or logic analyzer) would be very difficult, in my opinion.
Building Blocks
From this project, I now have an improved way to communicate between the 6502, Arduino, and PC. I have a 6502 routine to "save" the screen. Instead of sending it to a PC, I can leverage the code and add support to save to USB, SD cards, etc. on the Arduino. I can reverse the data flow quite easily, too, allowing me to load images into the 6502 from PC, USB, SD cards, etc.
In an earlier project, I used the ACIA to communicate from the 6502 to an Arduino to offload environmental calculations. While that worked fine, the performance wasn't great, and I really didn't care for handling serial data in interrupts from the ACIA. SPI will let me simplify the approach and improve performance at the same time. (I knew that going into the ACIA project, but I wanted to learn a bit about the ACIA regardless.)
Closing
I achieved my goal of implementing SPI between my 6502 and an Arduino. I got better at working with shift registers, and I learned some new tricks on my oscilloscope. I enjoyed this project, and I hope you find this helpful! If you have questions or suggestions, let me know! Thanks!
Postscript
I added support to print screen to an OLED screen.
And here's the refresh when serial isn't slowing things down, for comparison with the original video showing refresh on the PC.
Comments