|
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