Picante: Render Buffer Go Bye-Bye

What's gone wrong

My initial approach to rendering in a timely manner involved native/C code to 'blit' bitmaps to an 8bpp render buffer.  Every frame, that render buffer is expanded into 16bpp stripes for transfer to the display.  At about 18-19fps, this was pretty tidy.

The next step I wanted to take was to render tilemaps to the background, so I found a tileset online and converted into bytes() objects in a .py file for import...and promptly ran out of RAM.

The New Proposed Approach

So then I started looking at a 4bpp (16 colour) render buffer with colour palette, and I didn't like the amount of pixel operations involved in drawing to it, let alone expanding it out to the stripe for display.

So my intention now is to store a list of render commands for each stripe of the display.  These commands could be partial 'blits' of a bitmap, or straight colour-fill, or whatever else.  The key thing is that they are only actually executed once all render commands have been given and everything's ready for the transfer.

This would mean individual bitmaps could be 4bpp 16-colour with palette, but they could choose from the whole RGB565 colour space of the display.  It would also mean that the blitting and display transfer could be done on the second core fairly easily.

First Step Hits Brick Wall: Shocker

I decided my first step was to move the SPI/Display code into the native/C module to simplify the whole structure and require fewer .py files to be uploaded to the Pico...but I couldn't figure out how to include files from the Pico SDK from the native module.

Then I properly read this page, which says the mpy module is linked against a firmware symbol table that can change with different versions of the firmware.  This means that my native mpy module is only guaranteed to work with the exact version of the firmware that I compile it against.  When other people deployed the .mpy module to their Pico, there's no guarantee it would work.

Two Ways Forward

That leaves me only two ways forward that I can see:

  1. Build custom firmware which contains the picante module so it can access internal functions easily
  2. Keep any hardware access in Python code and only do generic functions in C to improve any bottlenecks.

I don't want to be re-flashing the firmware every time I change something about the module, so for now I'm going to go with option 2.  If hardware access through micropython turns out to be a bottleneck, I can port any python code to C and directly include the generic stuff I've already written.

So What Now?

So now I dust myself off and write a split-language module with a main picante.py module which imports a native picante_c.mpy module.  Hopefully that structure will work and I can get down to the render system changes I was targeting in the beginning. :/

Comments

Popular posts from this blog

Micro:Bit and SPI display

DCS World with TrackIR under Ubuntu

Cardboard Mock-up of USB Joystick