Hardware Accelerated Lower Bit Depths: Working!

A project log for VGA Graphics Over SPI and Serial - VGATonic

640x480 (and 848x480!) Color VGA Video Card for Microcontrollers and Single Board Computers

PKPK 06/28/2015 at 19:220 Comments

At least I'm publishing this post at a reasonable hour - I'm happy to announce I've got lower bit depth colors working!

If you just want to see the code, I posted it on Github.

Let's dive in for the rest of you; here's VGAtonic being meta and browsing on its own page in 640x480 at 1 bit color (translation: Black and White. If you're just following us now, we started with color and we're working backwards to support slower parts):

Gross, Black and White?

(For the record: This release also includes 4 bit color - 16 colors, and 2 bit - 4 'colors' consisting of black, white, and 2 grays)

Well, I'm excited about the Black and White anyway.

The point, with apologies to Dennis Rodman, is you can set up VGATonic "as bad as you want it to be".

If you've got fast SPI? Sure, 640x480x8bpp

If you've got slow SPI, or you're bitbanging it? Well, as of the release today you can go as low as 80x60x1bpp.

Here are the stats; bpS is 'bits per Screen'

If you're willing to drop down to 80x60x1bpp, that's a 512x speedup. You could bitbang at 100 kilohertz and still get around 21 frames per second for full screen refreshes. The 56k modem you dialed into AOL with could do 11 and change frames per second.

The Theory

In the last article I talked about how we could do tricky things with our LSBs to move around the screen and sit on certain pixels, and when we wrote to VGAtonic we just skipped to those positions.

Colors, it turns out, are even easier - in a single SPI 8 bit 'transaction', you just pack more pixels in. So, once VGAtonic 'knows' it is in a lower bit depth mode, it will start to shift pixels out of the single byte.

That means something like this:

For Clock = "000" to "111" do this:

    Pixel <- Data >> Clock
And to unroll the loop, for B&W:
If Clock == 0
  Pixel <- Data (shift right) 7
If Clock == 1
  Pixel <- Data (shift right) 6
If Clock == 2
  Pixel <- Data (shift right) 5
If Clock == 3
  Pixel <- Data (shift right) 4
If Clock == 4
  Pixel <- Data (shift right) 3
If Clock == 5
  Pixel <- Data (shift right) 2
If Clock == 6
  Pixel <- Data (shift right) 1
If Clock == 7
  Pixel <- Data (shift right) 0
Check it out on Github to see what I did in VHDL.

A Note on the Platform Change

I hinted at it in my last post on hardware assisted lower-resolutions, but I switched platforms and I'm doing this current work with an Odroid C1 instead of the Raspberry Pi 2 B from the initial demo (the one I played Doom on). The Pi has nuked 4 SD cards - so, yeah, I'll port all the new features when I'm happy with the progress, but the C1 has been reliable since I switched.

But, hey, I've now seen it working on an Intel Edison (I'll revisit it soon - I was having SPI issues), an Odroid C1, a Raspberry Pi 2 B, and various flavors of microcontrollers. That's worth something!