Close

#8 - Graphics (Practice)

A project log for Game-o-Tron Mini

A roughly credit card sized gaming handheld

david-boucherDavid Boucher 08/22/2017 at 20:130 Comments

Having worked out what how I wanted the graphics to work the next step was to implement it, which turned out to be fairly straightforward. Starting with the 16 bits per pixel, full colour framebuffer (see previous log), I wrote a program that would repeatedly fill the framebuffer with a random colour and then time how long in microseconds it took to transfer the framebuffer to the OLED.

The first version took the initialisation code from the Adafruit library and used a modified version of the screen clearing routine to transfer the data. This resulted in a figure of 26 FPS (Frames Per Second). Not terrible but not that great either.

One thing that I'd like to point out here: the Adafruit code is designed with a different goal to what I'm after, namely to be run on Arduinos that are very memory constrained. Therefore it has to write directly to the display as there's probably not going to be enough memory for a framebuffer. If it sounds like I'm knocking their code for poor performance that's not my intention and I'm glad they support their products in the way they do.

The first change that I made was seeing how high I could set the SPI frequency and get reliable operation. I found that this was 11Mhz; any higher than that and the transfer would sometimes fail part way through resulting in a partially filled screen.

After that I looked at the SPI transfer code itself. This uses SPI.transfer() and originally transferred a byte at a time but there are versions of SPI.transfer() that can do 16bit transfers and arbitrary length blocks of memory. Changing to a 16bit transfer gave me 34FPS and transferring a  line of data at a time gave me 42FPS which I think is more than enough.

I also accidentally found out that if you use the version of SPI.transfer() that takes a memory buffer to transfer, it clears the buffer. I think that it's supposed to be filled with the data coming back from the device but as there is none in this case, and I don't have that pin connected anyway, I get all zeros. It does mean that I have to make a copy of the line of data I'll be transferring or the framebuffer gets cleared to black on each update. If this is something that you actually want you can take the copy out and get 43FPS.

Once I had the full colour version working, I wrote the palettised 256 colour version. That was slightly slower as it needs to do the palette to pixel colour conversion but still managed 40FPS.

Of course the graphics routines are far from finished, I will need code for drawing into the framebuffer and it might be possible to optimise the transfer further, but I'll leave those things for another log.

Discussions