Skip to content

Commit 0c48ca6

Browse files
committed
feat(ssd1327): Add blink animation example using framebuf blit and pixel scaling.
1 parent 31ca15a commit 0c48ca6

1 file changed

Lines changed: 232 additions & 0 deletions

File tree

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
"""Blink animation example using framebuf blit and pixel scaling on SSD1327 OLED.
2+
3+
Displays a scaled 16x16 eye bitmap centered on the 128x128 round OLED screen
4+
and animates a smooth blink sequence by cycling through five eye states.
5+
6+
Demonstrates:
7+
- framebuf.FrameBuffer creation from raw bitmap data (MONO_HLSB)
8+
- Pixel-by-pixel scaling using fill_rect
9+
- framebuf.blit() to copy a scaled bitmap onto the display framebuffer
10+
- Frame-based animation with variable timing per frame
11+
"""
12+
13+
from time import sleep_ms
14+
15+
import framebuf
16+
import micropython
17+
import ssd1327
18+
from machine import SPI, Pin
19+
20+
# === Display setup ===
21+
spi = SPI(1)
22+
dc = Pin("DATA_COMMAND_DISPLAY")
23+
res = Pin("RST_DISPLAY")
24+
cs = Pin("CS_DISPLAY")
25+
display = ssd1327.WS_OLED_128X128_SPI(spi, dc, res, cs)
26+
27+
# === Bitmap dimensions and scale ===
28+
EYE_W = 16
29+
EYE_H = 16
30+
SCALE = 6 # Each pixel becomes a 6x6 block → 96x96px on screen
31+
32+
# === Eye bitmaps (MONO_HLSB, 16x16, 2 bytes per row) ===
33+
34+
EYE_OPEN = bytearray(
35+
[
36+
0b00000000,
37+
0b00000000,
38+
0b00111111,
39+
0b10000000,
40+
0b01000000,
41+
0b01000000,
42+
0b10011001,
43+
0b10010000,
44+
0b10100101,
45+
0b01010000,
46+
0b10000001,
47+
0b10000000,
48+
0b01000000,
49+
0b01000000,
50+
0b00111111,
51+
0b10000000,
52+
0b00000000,
53+
0b00000000,
54+
0b00000000,
55+
0b00000000,
56+
0b00000000,
57+
0b00000000,
58+
0b00000000,
59+
0b00000000,
60+
0b00000000,
61+
0b00000000,
62+
0b00000000,
63+
0b00000000,
64+
0b00000000,
65+
0b00000000,
66+
0b00000000,
67+
0b00000000,
68+
]
69+
)
70+
71+
EYE_SQUINT = bytearray(
72+
[
73+
0b00000000,
74+
0b00000000,
75+
0b00111111,
76+
0b10000000,
77+
0b01000000,
78+
0b01000000,
79+
0b10011001,
80+
0b10010000,
81+
0b10011001,
82+
0b10010000,
83+
0b10000001,
84+
0b10000000,
85+
0b01000000,
86+
0b01000000,
87+
0b00111111,
88+
0b10000000,
89+
0b00000000,
90+
0b00000000,
91+
0b00000000,
92+
0b00000000,
93+
0b00000000,
94+
0b00000000,
95+
0b00000000,
96+
0b00000000,
97+
0b00000000,
98+
0b00000000,
99+
0b00000000,
100+
0b00000000,
101+
0b00000000,
102+
0b00000000,
103+
0b00000000,
104+
0b00000000,
105+
]
106+
)
107+
108+
EYE_HALF = bytearray(
109+
[
110+
0b00000000,
111+
0b00000000,
112+
0b00111111,
113+
0b10000000,
114+
0b01000000,
115+
0b01000000,
116+
0b10000001,
117+
0b10010000,
118+
0b10111101,
119+
0b01010000,
120+
0b10000001,
121+
0b10000000,
122+
0b01000000,
123+
0b01000000,
124+
0b00111111,
125+
0b10000000,
126+
0b00000000,
127+
0b00000000,
128+
0b00000000,
129+
0b00000000,
130+
0b00000000,
131+
0b00000000,
132+
0b00000000,
133+
0b00000000,
134+
0b00000000,
135+
0b00000000,
136+
0b00000000,
137+
0b00000000,
138+
0b00000000,
139+
0b00000000,
140+
0b00000000,
141+
0b00000000,
142+
]
143+
)
144+
145+
EYE_CLOSED = bytearray(
146+
[
147+
0b00000000,
148+
0b00000000,
149+
0b00111111,
150+
0b10000000,
151+
0b01000000,
152+
0b01000000,
153+
0b10000000,
154+
0b00010000,
155+
0b10111111,
156+
0b11010000,
157+
0b10000000,
158+
0b00000000,
159+
0b01000000,
160+
0b01000000,
161+
0b00111111,
162+
0b10000000,
163+
0b00000000,
164+
0b00000000,
165+
0b00000000,
166+
0b00000000,
167+
0b00000000,
168+
0b00000000,
169+
0b00000000,
170+
0b00000000,
171+
0b00000000,
172+
0b00000000,
173+
0b00000000,
174+
0b00000000,
175+
0b00000000,
176+
0b00000000,
177+
0b00000000,
178+
0b00000000,
179+
]
180+
)
181+
182+
# === Animation: open → squint → half → closed → half → squint → open ===
183+
BLINK_FRAMES = [
184+
EYE_OPEN,
185+
EYE_SQUINT,
186+
EYE_HALF,
187+
EYE_CLOSED,
188+
EYE_CLOSED,
189+
EYE_HALF,
190+
EYE_SQUINT,
191+
EYE_OPEN,
192+
]
193+
194+
FRAME_DELAYS = [1200, 60, 50, 40, 40, 50, 60, 400] # ms per frame
195+
196+
197+
@micropython.native
198+
def draw_eye(bitmap):
199+
"""Draw a scaled eye bitmap centered on the 128x128 display."""
200+
buf = framebuf.FrameBuffer(bitmap, EYE_W, EYE_H, framebuf.MONO_HLSB)
201+
202+
scaled_w = EYE_W * SCALE
203+
scaled_h = EYE_H * SCALE
204+
scaled_bitmap = bytearray((scaled_w * scaled_h) // 8)
205+
scaled_buf = framebuf.FrameBuffer(
206+
scaled_bitmap, scaled_w, scaled_h, framebuf.MONO_HLSB
207+
)
208+
209+
# Scale up pixel by pixel
210+
for y in range(EYE_H):
211+
for x in range(EYE_W):
212+
if buf.pixel(x, y):
213+
scaled_buf.fill_rect(x * SCALE, y * SCALE, SCALE, SCALE, 1)
214+
215+
x_offset = (128 - scaled_w) // 2
216+
y_offset = (128 - scaled_h) // 2
217+
display.fill(0)
218+
display.framebuf.blit(scaled_buf, x_offset, y_offset)
219+
display.show()
220+
221+
222+
# === Animation loop ===
223+
try:
224+
while True:
225+
for frame, delay in zip(BLINK_FRAMES, FRAME_DELAYS):
226+
draw_eye(frame)
227+
sleep_ms(delay)
228+
except KeyboardInterrupt:
229+
pass
230+
finally:
231+
display.fill(0)
232+
display.show()

0 commit comments

Comments
 (0)