Correct me if I'm wrong, but all this sounds like you want to display some pixmap or bitmap via a framebuf interface.
If that assumption is wrong, the following might still help someone else.
But if that is what you are asking, then why not use a framebuf object in the source code right away? To demonstrate what I mean I created this little Smile in my favorite bitmap editor (pinta):
- smile1_source.png (2.5 KiB) Viewed 8480 times
Saved that as a .BMP file. Now I convert that into a very old bitmap format (binary PBM file format 'P4' by Jef Poskanzer). That stuff dates back to the 1980's, but the fun here is that the data of that bitmap is arranged EXACTLY as it is in a MONO_HLSB type MicroPython FrameBuffer.
That
convert(1) command comes from
ImageMagick, a highly recommended toolbox on Unix if you do anything with images at all.
The
smile1.pbm file will contain two '\n' terminated lines. The first one identifying the file format 'P4' (monochrome bitmap binary) and the second '<width> <height>' in decimal, space separated. The remaining bytes in that file are the binary bitmap data.
Yeah, I couldn't even draw a perfect circle and note that one pixel on the left cheek is missing ... darn.
Anyhow, that file format is trivial to read, so a rather simple Python script
Code: Select all
#!/usr/bin/env python
import sys
import os
def main():
if len(sys.argv) != 2:
usage()
return 2
with open(sys.argv[1], 'rb') as fd:
pbm_format = fd.readline().strip()
if pbm_format != b'P4':
print("ERROR: input file must be binary PBM (type P4)",
file = sys.stderr)
return 1
pbm_dims = [int(d) for d in fd.readline().strip().split()]
pbm_data = fd.read()
fbbase = "fb_{0}".format(os.path.basename(sys.argv[1]))
fbname = os.path.splitext(fbbase)[0]
with sys.stdout as fd:
f = "{0} = framebuf.FrameBuffer(bytearray({1}), {2}, {3}, framebuf.MONO_HLSB)\n"
fd.write(f.format(fbname, str(pbm_data), pbm_dims[0], pbm_dims[1]))
def usage():
print("""usage: {0} PBM_FILE""".format(os.path.basename(sys.argv[0])),
file = sys.stderr)
if __name__ == '__main__':
main()
will convert that
smile1.pbm file into the following output:
Code: Select all
fb_smile1 = framebuf.FrameBuffer(bytearray(b'\x00~\x00\x03\xff\xc0\x07\x81\xe0\x1e\x00x8\x00\x1c0\x00\x0c`\x00\x0ea\xc3\x86\xe0\x00\x07\xc0\x00\x03\xc0\x00\x03\xc0\x00\x02\xc0\x00\x03\xc0\x00\x03\xe0B\x07`<\x06`\x00\x060\x00\x0c8\x00\x1c\x1e\x00x\x07\x81\xe0\x03\xff\xc0\x00\xff\x00'), 24, 23, framebuf.MONO_HLSB)
Now
fb_smile1 is a FrameBuffer object, 24x23 pixels in MONO_HLSB format. So the MicroPython script
Code: Select all
from machine import I2C, Pin
import ssd1306
import framebuf
i2c = I2C(-1, scl=Pin(22), sda=Pin(21))
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
fb_smile1 = framebuf.FrameBuffer(bytearray(b'\x00~\x00\x03\xff\xc0\x07\x81\xe0\x1e\x00x8\x00\x1c0\x00\x0c`\x00\x0ea\xc3\x86\xe0\x00\x07\xc0\x00\x03\xc0\x00\x03\xc0\x00\x02\xc0\x00\x03\xc0\x00\x03\xe0B\x07`<\x06`\x00\x060\x00\x0c8\x00\x1c\x1e\x00x\x07\x81\xe0\x03\xff\xc0\x00\xff\x00'), 24, 23, framebuf.MONO_HLSB)
oled.fill(0)
oled.framebuf.blit(fb_smile1, 0, 20)
oled.text("Hello", 30, 20)
oled.text("MicroPython", 30, 28)
oled.show()
will produce this display (still missing one pixel on the left cheek):
- IMG_20191225_211256.jpg (228.54 KiB) Viewed 8480 times
Is that what you were looking for?
I am sure the same technique could be adopted for display types with more bits per pixel (grayscale or color). Although the conversion might get a bit more complicated than this monochrome example. It might also help to convert the FrameBuffer to the display's native format (the SSD1306 is MONO_VLSB, not MONO_HLSB), but I haven't studied the FrameBuffer C code enough to say for sure.
Regards, Jan