|
16 | 16 | **Hardware:**
|
17 | 17 |
|
18 | 18 | * `Adafruit SSD1306 OLED displays <https://www.adafruit.com/?q=ssd1306>`_
|
| 19 | +* `Adafruit HT16K33 Matrix displays <https://www.adafruit.com/?q=ht16k33>`_ |
19 | 20 |
|
20 | 21 | **Software and Dependencies:**
|
21 | 22 |
|
|
36 | 37 | GS4_HMSB = 2 # Unimplemented!
|
37 | 38 | MHMSB = 3 # Single bit displays like the Sharp Memory
|
38 | 39 | RGB888 = 4 # Neopixels and Dotstars
|
| 40 | +GS2_HMSB = 5 # 2-bit color displays like the HT16K33 8x8 Matrix |
| 41 | + |
| 42 | + |
| 43 | +class GS2HMSBFormat: |
| 44 | + """GS2HMSBFormat""" |
| 45 | + |
| 46 | + @staticmethod |
| 47 | + def set_pixel(framebuf, x, y, color): |
| 48 | + """Set a given pixel to a color.""" |
| 49 | + index = (y * framebuf.stride + x) >> 2 |
| 50 | + pixel = framebuf.buf[index] |
| 51 | + |
| 52 | + shift = (x & 0b11) << 1 |
| 53 | + mask = 0b11 << shift |
| 54 | + color = (color & 0b11) << shift |
| 55 | + |
| 56 | + framebuf.buf[index] = color | (pixel & (~mask)) |
| 57 | + |
| 58 | + @staticmethod |
| 59 | + def get_pixel(framebuf, x, y): |
| 60 | + """Get the color of a given pixel""" |
| 61 | + index = (y * framebuf.stride + x) >> 2 |
| 62 | + pixel = framebuf.buf[index] |
| 63 | + |
| 64 | + shift = (x & 0b11) << 1 |
| 65 | + return (pixel >> shift) & 0b11 |
| 66 | + |
| 67 | + @staticmethod |
| 68 | + def fill(framebuf, color): |
| 69 | + """completely fill/clear the buffer with a color""" |
| 70 | + if color: |
| 71 | + bits = color & 0b11 |
| 72 | + fill = (bits << 6) | (bits << 4) | (bits << 2) | (bits << 0) |
| 73 | + else: |
| 74 | + fill = 0x00 |
| 75 | + |
| 76 | + framebuf.buf = [fill for i in range(len(framebuf.buf))] |
| 77 | + |
| 78 | + @staticmethod |
| 79 | + def rect(framebuf, x, y, width, height, color): |
| 80 | + """Draw the outline of a rectangle at the given location, size and color.""" |
| 81 | + # pylint: disable=too-many-arguments |
| 82 | + for _x in range(x, x + width): |
| 83 | + for _y in range(y, y + height): |
| 84 | + if _x in [x, x + width] or _y in [y, y + height]: |
| 85 | + GS2HMSBFormat.set_pixel(framebuf, _x, _y, color) |
| 86 | + |
| 87 | + @staticmethod |
| 88 | + def fill_rect(framebuf, x, y, width, height, color): |
| 89 | + """Draw the outline and interior of a rectangle at the given location, size and color.""" |
| 90 | + # pylint: disable=too-many-arguments |
| 91 | + for _x in range(x, x + width): |
| 92 | + for _y in range(y, y + height): |
| 93 | + GS2HMSBFormat.set_pixel(framebuf, _x, _y, color) |
39 | 94 |
|
40 | 95 |
|
41 | 96 | class MHMSBFormat:
|
@@ -256,6 +311,8 @@ def __init__(self, buf, width, height, buf_format=MVLSB, stride=None):
|
256 | 311 | self.format = RGB888Format()
|
257 | 312 | elif buf_format == RGB565:
|
258 | 313 | self.format = RGB565Format()
|
| 314 | + elif buf_format == GS2_HMSB: |
| 315 | + self.format = GS2HMSBFormat() |
259 | 316 | else:
|
260 | 317 | raise ValueError("invalid format")
|
261 | 318 | self._rotation = 0
|
@@ -480,9 +537,7 @@ def image(self, img):
|
480 | 537 | imwidth, imheight = img.size
|
481 | 538 | if imwidth != width or imheight != height:
|
482 | 539 | raise ValueError(
|
483 |
| - "Image must be same dimensions as display ({0}x{1}).".format( |
484 |
| - width, height |
485 |
| - ) |
| 540 | + f"Image must be same dimensions as display ({width}x{height})." |
486 | 541 | )
|
487 | 542 | # Grab all the pixels from the image, faster than getpixel.
|
488 | 543 | pixels = img.load()
|
|
0 commit comments