2 Bit Image Format

Here is what I have been experimenting with using 2 Bits per pixel to store images. This allows for easy implementation of gray and transparency. The code is still pretty rough and could use some optimizing. If you have any suggestions, let me know!

Demo Sketch
Get the demo sketch on GitHub here. The DrawTest sketch lets you control Link from Link’s Awakening around the Arduboy screen. Just a demo of the draw method.

Graphics Converter
Here is the tool I created to convert PNG files into the 2 Bit format. The tool also works to convert images into 1 BPP code that is compatible with drawBitmap. This is very unfinished software so everything may not work as it appears it should.

I’m using DropBox for this since I’m not sure what else to use, hopefully it works.
Download the editor here
The editor can also convert an animation by making a horizontal strip of images all the same height and width.



There has been some work in the hardware to try and get grayscale, it is possible but you end up with scanlines and flickering. We are working to try and get the factory to break out frame sync signal onto the pin interface so we can do grayscale so in that case this will be perfect tool to get started. Nice!

I believe it can be optimized by removing the temporary bytes and shifting the translated bits directly into the display buffer. When I get some time I’ll try to get it more efficient.

I think 3 or 4 shades total could be really cool to work with in the future. There are incredible games on the gameboy and it has an extremely limited palette.

I’m not in any rush for the next version though, I’m amazed at what can be accomplished with only 2 colors.

To do fake greyscale you’re limited by the hardwares maximum refresh rate. For instance to generate 60 FPS b/w you need 60 FPS. To generate 60 FPS with black, white, and grey you now need the “grey” on the screen to be 50% cycle, which requires double the frame rate (to turn them on and off inside 50 FPS)… so that means 120 FPS. The OLED itself combined with our hardware SPI has an effective cap of around 150 FPS I believe. That means:

  • 150 FPS 2 color (B/W)
  • 75 FPS 3 color (B/W/grey)
  • 50 FPS 4 color (B/w/two greys)

These all look reasonably good on the hardware except for the vertical sync tearing. Of course for memory constraint issues 3 color + transparency is really a sweet spot. The harder part becomes buffering the screen since a true 2 bit color experience would require 2k of the total 2.5k RAM just to buffer the screen. So what you really want at that point is a rendering system that could avoid having to buffer the screen. Complex but fun issues. :smile:

1 Like

Update: https://github.com/Arduboy/Arduboy/issues/89

This issue means there is really time inside the display() loop itself (if you dropped down to assembly) to have some opportunities here. You could have a 4 color tiled background rendered basically for “free” and then the 1kb buffer would be drawn overtop of that. Of course you’d need a 128 byte buffer just to store tile backgrounds (assuming 255 possibilities).

And of course there is still that pesky vsync issue.


That vsync issue is what bothers me the most. With smaller images it’s not so noticeable but for anything larger you’ll get a very apparent tear. Hopefully for the next version the sync pin will be available. I’m impressed with your low level knowledge! I’m learning assembly this semester and it is definitely a different world than C++.

This is going to require a damn miracle. Trying to get more access/information about our OLED display has been on the forefront of my activities here and China and it’s a rabbit hole I’ve not yet come close to finding the bottom of.

The vsyc pin is on the display controller, but the factory would need to break that pin out to the flexible ribbon connector that we have. There are unused pins so theoretically this is possible… However…

The factory has refused to even meet with me until I am ordering quantities of at least 100,000 units so unless I can marry the daughter of the factory boss or some such thing, please don’t hold your breath for this.

We will continue to this fight this battle but it’s a war of attrition, and not one we are well equipped to survive unless… Unless we some day are going to sell a million Arduboy. Which is an overwhelming thought.


@Dreamer3 I’ve been learning quite a bit of assembly this spring for x86 architecture. Do you have any suggestions where I could learn the instruction set and syntax for the Leonardo’s chip?

@Gaveno, The instruction set summary in Section 32, along with the rest of the Atmega32U4 datasheet, gives all the details. It’s not a tutorial but if you’ve learned the assembly instructions of other processor(s), such as x86, you may be able to understand it.

1 Like

Awesome, thank you! I noticed the code ends up in sort of a strange format with underscores in quotations when using asm volatile. Do you know of a reference that explains that part?

1 Like

@Gaveno, The Atmel AVR 8-bit Instruction Set document is another good reference.

1 Like

I haven’t looked into using AVR assembler in much detail. Perhaps this document could be of some help?


@MLXXXp that looks exactly like what I needed, thank you!