-
Notifications
You must be signed in to change notification settings - Fork 1
feat(ssd1327): Add blink animation example with framebuf scaling. #420
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,232 @@ | ||||||||||||||||||||||||||||||||||||||||||
| """Blink animation example using framebuf blit and pixel scaling on SSD1327 OLED. | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| Displays a scaled 16x16 eye bitmap centered on the 128x128 round OLED screen | ||||||||||||||||||||||||||||||||||||||||||
| and animates a smooth blink sequence by cycling through five eye states. | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| Demonstrates: | ||||||||||||||||||||||||||||||||||||||||||
| - framebuf.FrameBuffer creation from raw bitmap data (MONO_HLSB) | ||||||||||||||||||||||||||||||||||||||||||
| - Pixel-by-pixel scaling using fill_rect | ||||||||||||||||||||||||||||||||||||||||||
| - framebuf.blit() to copy a scaled bitmap onto the display framebuffer | ||||||||||||||||||||||||||||||||||||||||||
| - Frame-based animation with variable timing per frame | ||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| from time import sleep_ms | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| import framebuf | ||||||||||||||||||||||||||||||||||||||||||
| import micropython | ||||||||||||||||||||||||||||||||||||||||||
| import ssd1327 | ||||||||||||||||||||||||||||||||||||||||||
| from machine import SPI, Pin | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| # === Display setup === | ||||||||||||||||||||||||||||||||||||||||||
| spi = SPI(1) | ||||||||||||||||||||||||||||||||||||||||||
| dc = Pin("DATA_COMMAND_DISPLAY") | ||||||||||||||||||||||||||||||||||||||||||
| res = Pin("RST_DISPLAY") | ||||||||||||||||||||||||||||||||||||||||||
| cs = Pin("CS_DISPLAY") | ||||||||||||||||||||||||||||||||||||||||||
| display = ssd1327.WS_OLED_128X128_SPI(spi, dc, res, cs) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| # === Bitmap dimensions and scale === | ||||||||||||||||||||||||||||||||||||||||||
| EYE_W = 16 | ||||||||||||||||||||||||||||||||||||||||||
| EYE_H = 16 | ||||||||||||||||||||||||||||||||||||||||||
| SCALE = 6 # Each pixel becomes a 6x6 block → 96x96px on screen | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| # === Eye bitmaps (MONO_HLSB, 16x16, 2 bytes per row) === | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| EYE_OPEN = bytearray( | ||||||||||||||||||||||||||||||||||||||||||
| [ | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00111111, | ||||||||||||||||||||||||||||||||||||||||||
| 0b10000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b01000000, | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+32
to
+40
|
||||||||||||||||||||||||||||||||||||||||||
| 0b01000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b10011001, | ||||||||||||||||||||||||||||||||||||||||||
| 0b10010000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b10100101, | ||||||||||||||||||||||||||||||||||||||||||
| 0b01010000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b10000001, | ||||||||||||||||||||||||||||||||||||||||||
| 0b10000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b01000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b01000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00111111, | ||||||||||||||||||||||||||||||||||||||||||
| 0b10000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| EYE_SQUINT = bytearray( | ||||||||||||||||||||||||||||||||||||||||||
| [ | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00111111, | ||||||||||||||||||||||||||||||||||||||||||
| 0b10000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b01000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b01000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b10011001, | ||||||||||||||||||||||||||||||||||||||||||
| 0b10010000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b10011001, | ||||||||||||||||||||||||||||||||||||||||||
| 0b10010000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b10000001, | ||||||||||||||||||||||||||||||||||||||||||
| 0b10000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b01000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b01000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00111111, | ||||||||||||||||||||||||||||||||||||||||||
| 0b10000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| EYE_HALF = bytearray( | ||||||||||||||||||||||||||||||||||||||||||
| [ | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00111111, | ||||||||||||||||||||||||||||||||||||||||||
| 0b10000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b01000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b01000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b10000001, | ||||||||||||||||||||||||||||||||||||||||||
| 0b10010000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b10111101, | ||||||||||||||||||||||||||||||||||||||||||
| 0b01010000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b10000001, | ||||||||||||||||||||||||||||||||||||||||||
| 0b10000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b01000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b01000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00111111, | ||||||||||||||||||||||||||||||||||||||||||
| 0b10000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| EYE_CLOSED = bytearray( | ||||||||||||||||||||||||||||||||||||||||||
| [ | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00111111, | ||||||||||||||||||||||||||||||||||||||||||
| 0b10000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b01000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b01000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b10000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00010000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b10111111, | ||||||||||||||||||||||||||||||||||||||||||
| 0b11010000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b10000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b01000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b01000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00111111, | ||||||||||||||||||||||||||||||||||||||||||
| 0b10000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| 0b00000000, | ||||||||||||||||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| # === Animation: open → squint → half → closed → half → squint → open === | ||||||||||||||||||||||||||||||||||||||||||
| BLINK_FRAMES = [ | ||||||||||||||||||||||||||||||||||||||||||
| EYE_OPEN, | ||||||||||||||||||||||||||||||||||||||||||
| EYE_SQUINT, | ||||||||||||||||||||||||||||||||||||||||||
| EYE_HALF, | ||||||||||||||||||||||||||||||||||||||||||
| EYE_CLOSED, | ||||||||||||||||||||||||||||||||||||||||||
| EYE_CLOSED, | ||||||||||||||||||||||||||||||||||||||||||
| EYE_HALF, | ||||||||||||||||||||||||||||||||||||||||||
| EYE_SQUINT, | ||||||||||||||||||||||||||||||||||||||||||
| EYE_OPEN, | ||||||||||||||||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| FRAME_DELAYS = [1200, 60, 50, 40, 40, 50, 60, 400] # ms per frame | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| @micropython.native | ||||||||||||||||||||||||||||||||||||||||||
| def draw_eye(bitmap): | ||||||||||||||||||||||||||||||||||||||||||
| """Draw a scaled eye bitmap centered on the 128x128 display.""" | ||||||||||||||||||||||||||||||||||||||||||
| buf = framebuf.FrameBuffer(bitmap, EYE_W, EYE_H, framebuf.MONO_HLSB) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| scaled_w = EYE_W * SCALE | ||||||||||||||||||||||||||||||||||||||||||
| scaled_h = EYE_H * SCALE | ||||||||||||||||||||||||||||||||||||||||||
| scaled_bitmap = bytearray((scaled_w * scaled_h) // 8) | ||||||||||||||||||||||||||||||||||||||||||
| scaled_buf = framebuf.FrameBuffer( | ||||||||||||||||||||||||||||||||||||||||||
| scaled_bitmap, scaled_w, scaled_h, framebuf.MONO_HLSB | ||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+202
to
+207
|
||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| # Scale up pixel by pixel | ||||||||||||||||||||||||||||||||||||||||||
| for y in range(EYE_H): | ||||||||||||||||||||||||||||||||||||||||||
| for x in range(EYE_W): | ||||||||||||||||||||||||||||||||||||||||||
| if buf.pixel(x, y): | ||||||||||||||||||||||||||||||||||||||||||
| scaled_buf.fill_rect(x * SCALE, y * SCALE, SCALE, SCALE, 1) | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+204
to
+213
|
||||||||||||||||||||||||||||||||||||||||||
| scaled_bitmap = bytearray((scaled_w * scaled_h) // 8) | |
| scaled_buf = framebuf.FrameBuffer( | |
| scaled_bitmap, scaled_w, scaled_h, framebuf.MONO_HLSB | |
| ) | |
| # Scale up pixel by pixel | |
| for y in range(EYE_H): | |
| for x in range(EYE_W): | |
| if buf.pixel(x, y): | |
| scaled_buf.fill_rect(x * SCALE, y * SCALE, SCALE, SCALE, 1) | |
| scaled_bitmap = bytearray((scaled_w * scaled_h) // 2) | |
| scaled_buf = framebuf.FrameBuffer( | |
| scaled_bitmap, scaled_w, scaled_h, framebuf.GS4_HMSB | |
| ) | |
| # Scale up pixel by pixel | |
| for y in range(EYE_H): | |
| for x in range(EYE_W): | |
| if buf.pixel(x, y): | |
| scaled_buf.fill_rect(x * SCALE, y * SCALE, SCALE, SCALE, 15) |
Copilot
AI
Apr 20, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This hard-codes 128 for centering. Since the display object already exposes display.width / display.height, using those would keep the example correct if the driver is instantiated with a different resolution (and avoids duplicating the docstring assumption).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PR description/issue checklist mentions updating
lib/ssd1327/README.mdexamples table, but this PR only adds the example file. Please addblink_animation.pyto the README Examples table (or update the PR description if that task is intentionally out of scope).