Improving The Microcontroller Gaming Performance With PicoGame

The ability to write Python on microcontrollers with the likes of MicroPython and later CiruitPython has made them much more accessible. [MakerClassCZ] brings that to game development with PicoGame.

Like any good project, it starts with a problem that needs solving. Put simply, the existing CircuitPython libraries aren’t too impressive for gaming. The DisplayIO library tends to do full display refreshes, which are slow on such tiny displays, and the Stage library just wasn’t flexible enough for [MakerClassCZ]’s liking. So he built his own.

PicoGame, like the others, implements the performance-sensitive things in C, but does partial updates for the screen, on its own massively increasing the framerate. On the other end, it uses fixed-point math–much cheaper than soft-float–and makes an active effort to keep the RAM usage low so Python can have it. What’s even more clever is using the downtime between sending one tiny portion of frame to calculate the next just in time.

Of course, the display is still the limit. If you need to update a lot of it, you might end up with 10 FPS if you’re lucky. But if you can settle for less motion, you could see 100.

18 thoughts on “Improving The Microcontroller Gaming Performance With PicoGame

      1. +1 I’d like to try it out. pico8 on bare metal is damn nice. If you documented how you did your port that would be awesome guidance for people porting on other platforms.

  1. I think one if of the slowest python happy micro controllers i use regularly is a samd21 clocked at a weird ass 84MHz, and you’re telling me I can make intellevision grade games that run at 10fps on something that should … on paper kick a 80386 right in the dick?

    God I love python

    1. Well a 80386 had a lot of additional components, foremost a GPU. You can’t really compare MHz when you have different architectures, not just inside the CPU but also outside on the system. Sure 84MHz is a lot more than a typical 386SX at 25 MHz, but supporting systems make quite a difference.

      For instance;
      The Commodore PET and the C64 both have a 6502 CPU, but the additional system components make quite a difference.

      1. Well a 80386 had a lot of additional components, foremost a GPU.

        The main handicap with these microcontroller based devices is the SPI bus, which seems to be limited under 10 megabits per second in the typical case, while a 386 machine with an ISA bus video card can reach 8 mega bytes per second which is 64 Mbps.

        240 x 240 x 2 bytes per pixel equals 115200 bytes per screen, or 912000 bits per frame. For 30fps that’s over 27 million bits per second with zero overhead. In practice I’m guessing we get half of that. A lot of SPI ports only run at 10 or 20 MHz, so getting a consistent 30fps just isn’t going to happen. That’s just the nature of SPI. Desktop computer screens use protocols that can send more than one bit at a time, and operate much faster than 10Mhz. SPI just can’t.

  2. I always get confused with micropython vs circuitpython. So this is circuitpython only? Is it because circuitpython is more suitable to micropython? I thought that circuitpython wasn’t able to make use of second cores? To me using both cores seems valuable to games…

    1. The firmware is CircuitPython, but the engine is a portable C module – the same code already runs on MicroPython in the browser playground, and proper MicroPython support is in the works. So it’s not CircuitPython locked.

      I went with CircuitPython first for the ecosystem, not speed: displayio, ready-made board definitions, settings.toml, and the code.py on the “flash drive”. It is easier for beginners and classrooms.

      On the second core – you’re right that CP doesn’t expose it. But honestly it’s not the main lever here, because it adds synchronization complexity. The actual bottleneck is the SPI display push.

    1. Because often you do need to update the entire screen, and then it’s going to look bad if you can’t do it fast enough.

      I hate this mindset of “the average is enough”. It’s what ruined digital television – the averaged metrics show that the image quality is almost perfect, but the actual image looks like shit any time the camera moves.

      Imagine watching a nature documentary on digital broadcast TV, the camera pans over a majestic savanna with distant mountains in the horizon…. and the mountains stop moving while the rest of the scene pans on, and the whole thing jerks and snaps in place every 2-3 seconds because there’s not enough data for motion prediction between the key frames.

      Plastic foreheads and faces on people, grass disappearing and appearing on a football match, stuttering films and documentaries. Why is this “better”? It’s garbage – the only difference is that now we have 12 times more of it, because they crammed so many channels in the bandwidth of one.

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.