Skip to content

Commit 39325d6

Browse files
committed
Create SH1106 subclass of SSD1306
sh1106 is almost identical to ssd1306, but has four more vertical pixels.
1 parent cb184cd commit 39325d6

File tree

1 file changed

+63
-32
lines changed

1 file changed

+63
-32
lines changed

pslab/external/display.py

Lines changed: 63 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
>>> oled.scroll("stop")
1515
"""
1616
import json
17-
import time
1817
import os.path
1918

2019
from PIL import Image
@@ -25,7 +24,7 @@
2524

2625

2726
class SSD1306(I2CSlave):
28-
"""Interface to a monochrome OLED display.
27+
"""Interface to a monochrome OLED display driven by an SSD1306 chip.
2928
3029
Parameters
3130
----------
@@ -69,6 +68,7 @@ class SSD1306(I2CSlave):
6968
_ADDRESS = 0x3C
7069
_WIDTH = 128
7170
_HEIGHT = 64
71+
_LOWCOLUMNOFFSET = 0
7272

7373
_SETCONTRAST = 0x81
7474
_DISPLAYALLON_RESUME = 0xA4
@@ -116,8 +116,8 @@ class SSD1306(I2CSlave):
116116
]
117117
# fmt: on
118118

119-
def __init__(self, speed="slow", sh1106=False):
120-
super().__init__(self._ADDRESS)
119+
def __init__(self, device=None, speed="slow"):
120+
super().__init__(device=device, address=self._ADDRESS)
121121
self._buffer = [0 for a in range(1024)]
122122
self.cursor = [0, 0]
123123
self.textsize = 1
@@ -126,7 +126,6 @@ def __init__(self, speed="slow", sh1106=False):
126126
self.wrap = True
127127
self._contrast = 0xFF
128128
self.speed = speed
129-
self.sh1106 = sh1106
130129

131130
with open(os.path.join(__location__, "ssd1306_gfx.json"), "r") as f:
132131
gfx = json.load(f)
@@ -142,7 +141,6 @@ def __init__(self, speed="slow", sh1106=False):
142141
def display_logo(self):
143142
"""Display pslab.io logo."""
144143
self.scroll("stop")
145-
self.clear()
146144
self._buffer = self._logo[:]
147145
self.update()
148146

@@ -161,16 +159,20 @@ def clear(self):
161159
def update(self):
162160
"""Redraw display."""
163161
for i in range(8):
164-
self._write_command(self._SETLOWCOLUMN | 2 if self.sh1106 else 0)
162+
self._write_command(self._SETLOWCOLUMN | self._LOWCOLUMNOFFSET)
165163
self._write_command(self._SETHIGHCOLUMN | 0)
166164
self._write_command(self._SETPAGESTART | i)
167165

168166
if self.speed == "slow":
169167
for j in range(self._WIDTH):
170-
self._write_data([self._buffer[i*self._WIDTH + j]])
168+
self._write_data([self._buffer[i * self._WIDTH + j]])
171169
elif self.speed == "medium":
172170
for j in range(self._WIDTH // 8):
173-
self._write_data(self._buffer[i*self._WIDTH + j*8 : i*self._WIDTH + 8*(j+1)])
171+
self._write_data(
172+
self._buffer[
173+
i * self._WIDTH + j * 8 : i * self._WIDTH + 8 * (j + 1)
174+
]
175+
)
174176
else:
175177
self._write_data(self._buffer[self._WIDTH * i : self._WIDTH * (i + 1)])
176178

@@ -342,16 +344,26 @@ def _draw_char(self, x0, y0, c, color, bg, size):
342344
if size == 1:
343345
self.draw_pixel(x0 + i, y0 + j, color, False)
344346
else:
345-
self.fill_rectangle(x0 + (i * size), y0 + (j * size), size, size, color, False)
347+
self.fill_rectangle(
348+
x0 + (i * size), y0 + (j * size), size, size, color, False
349+
)
346350
elif bg != color:
347351
if size == 1:
348352
self.draw_pixel(x0 + i, y0 + j, bg, False)
349353
else:
350-
self.fill_rect(x0 + i * size, y0 + j * size, size, size, bg, False)
354+
self.fill_rectangle(
355+
x0 + i * size, y0 + j * size, size, size, bg, False
356+
)
351357
line >>= 1
352358

353-
def scroll(self, direction):
354-
"""Scroll the screen contents."""
359+
def scroll(self, direction: str):
360+
"""Scroll the screen contents.
361+
362+
Parameters
363+
----------
364+
direction : {'left', 'right', 'stop'}
365+
Scrolling direction.
366+
"""
355367
if direction == "left":
356368
self._write_command(0x27) # up-0x29 ,2A left-0x27 right0x26
357369
if direction == "right":
@@ -361,7 +373,14 @@ def scroll(self, direction):
361373
if direction in ["topleft", "bottomleft"]:
362374
self._write_command(0x2A) # up-0x29 ,2A left-0x27 right0x26
363375

364-
if direction in ["left", "right", "topright", "topleft", "bottomleft", "bottomright"]:
376+
if direction in [
377+
"left",
378+
"right",
379+
"topright",
380+
"topleft",
381+
"bottomleft",
382+
"bottomright",
383+
]:
365384
self._write_command(0x0) # dummy
366385
self._write_command(0x0) # start page
367386
self._write_command(0x7) # time interval 0b100 - 3 frames
@@ -380,13 +399,13 @@ def scroll(self, direction):
380399
if direction == "stop":
381400
self._write_command(0x2E)
382401

383-
def pulse(self):
384-
"""Turn the display on and off."""
385-
for a in range(2):
386-
self._write_command(self._DISPLAYOFF)
387-
time.sleep(0.1)
388-
self._write_command(self._DISPLAYON)
389-
time.sleep(0.1)
402+
def poweron(self):
403+
"""Turn the display on."""
404+
self._write_command(self._DISPLAYON)
405+
406+
def poweroff(self):
407+
"""Turn the display off."""
408+
self._write_command(self._DISPLAYOFF)
390409

391410
def display(self, image: Image):
392411
"""Display an image.
@@ -397,10 +416,10 @@ def display(self, image: Image):
397416
A PIL.Image instance.
398417
"""
399418
if not image.size == (128, 64):
400-
image.resize((128, 64))
419+
image = image.resize((128, 64))
401420

402421
if not image.mode == "1":
403-
image.convert("1")
422+
image = image.convert("1")
404423

405424
image_data = image.getdata()
406425
pixels_per_page = self._WIDTH * 8
@@ -411,17 +430,29 @@ def display(self, image: Image):
411430
offsets = [y + self._WIDTH * i for i in range(8)]
412431

413432
for x in range(self._WIDTH):
414-
buf[x] = \
415-
(image_data[x + offsets[0]] and 0x01) | \
416-
(image_data[x + offsets[1]] and 0x02) | \
417-
(image_data[x + offsets[2]] and 0x04) | \
418-
(image_data[x + offsets[3]] and 0x08) | \
419-
(image_data[x + offsets[4]] and 0x10) | \
420-
(image_data[x + offsets[5]] and 0x20) | \
421-
(image_data[x + offsets[6]] and 0x40) | \
422-
(image_data[x + offsets[7]] and 0x80)
433+
buf[x] = (
434+
(image_data[x + offsets[0]] and 0x01)
435+
| (image_data[x + offsets[1]] and 0x02)
436+
| (image_data[x + offsets[2]] and 0x04)
437+
| (image_data[x + offsets[3]] and 0x08)
438+
| (image_data[x + offsets[4]] and 0x10)
439+
| (image_data[x + offsets[5]] and 0x20)
440+
| (image_data[x + offsets[6]] and 0x40)
441+
| (image_data[x + offsets[7]] and 0x80)
442+
)
423443

424444
buffer += list(buf)
425445

426446
self._buffer = buffer
427447
self.update()
448+
449+
450+
class SH1106(SSD1306):
451+
"""Interface to a monochrome OLED display driven by an SH1106 chip.
452+
453+
SH1106 is a common OLED driver which is almost identical to the SSD1306.
454+
OLED displays are sometimes advertised as using SSD1306 when they in fact
455+
use SH1106.
456+
"""
457+
458+
_LOWCOLUMNOFFSET = 2

0 commit comments

Comments
 (0)