14
14
>>> oled.scroll("stop")
15
15
"""
16
16
import json
17
- import time
18
17
import os .path
19
18
20
19
from PIL import Image
25
24
26
25
27
26
class SSD1306 (I2CSlave ):
28
- """Interface to a monochrome OLED display.
27
+ """Interface to a monochrome OLED display driven by an SSD1306 chip .
29
28
30
29
Parameters
31
30
----------
@@ -69,6 +68,7 @@ class SSD1306(I2CSlave):
69
68
_ADDRESS = 0x3C
70
69
_WIDTH = 128
71
70
_HEIGHT = 64
71
+ _LOWCOLUMNOFFSET = 0
72
72
73
73
_SETCONTRAST = 0x81
74
74
_DISPLAYALLON_RESUME = 0xA4
@@ -116,8 +116,8 @@ class SSD1306(I2CSlave):
116
116
]
117
117
# fmt: on
118
118
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 )
121
121
self ._buffer = [0 for a in range (1024 )]
122
122
self .cursor = [0 , 0 ]
123
123
self .textsize = 1
@@ -126,7 +126,6 @@ def __init__(self, speed="slow", sh1106=False):
126
126
self .wrap = True
127
127
self ._contrast = 0xFF
128
128
self .speed = speed
129
- self .sh1106 = sh1106
130
129
131
130
with open (os .path .join (__location__ , "ssd1306_gfx.json" ), "r" ) as f :
132
131
gfx = json .load (f )
@@ -142,7 +141,6 @@ def __init__(self, speed="slow", sh1106=False):
142
141
def display_logo (self ):
143
142
"""Display pslab.io logo."""
144
143
self .scroll ("stop" )
145
- self .clear ()
146
144
self ._buffer = self ._logo [:]
147
145
self .update ()
148
146
@@ -161,16 +159,20 @@ def clear(self):
161
159
def update (self ):
162
160
"""Redraw display."""
163
161
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 )
165
163
self ._write_command (self ._SETHIGHCOLUMN | 0 )
166
164
self ._write_command (self ._SETPAGESTART | i )
167
165
168
166
if self .speed == "slow" :
169
167
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 ]])
171
169
elif self .speed == "medium" :
172
170
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
+ )
174
176
else :
175
177
self ._write_data (self ._buffer [self ._WIDTH * i : self ._WIDTH * (i + 1 )])
176
178
@@ -342,16 +344,26 @@ def _draw_char(self, x0, y0, c, color, bg, size):
342
344
if size == 1 :
343
345
self .draw_pixel (x0 + i , y0 + j , color , False )
344
346
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
+ )
346
350
elif bg != color :
347
351
if size == 1 :
348
352
self .draw_pixel (x0 + i , y0 + j , bg , False )
349
353
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
+ )
351
357
line >>= 1
352
358
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
+ """
355
367
if direction == "left" :
356
368
self ._write_command (0x27 ) # up-0x29 ,2A left-0x27 right0x26
357
369
if direction == "right" :
@@ -361,7 +373,14 @@ def scroll(self, direction):
361
373
if direction in ["topleft" , "bottomleft" ]:
362
374
self ._write_command (0x2A ) # up-0x29 ,2A left-0x27 right0x26
363
375
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
+ ]:
365
384
self ._write_command (0x0 ) # dummy
366
385
self ._write_command (0x0 ) # start page
367
386
self ._write_command (0x7 ) # time interval 0b100 - 3 frames
@@ -380,13 +399,13 @@ def scroll(self, direction):
380
399
if direction == "stop" :
381
400
self ._write_command (0x2E )
382
401
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 )
390
409
391
410
def display (self , image : Image ):
392
411
"""Display an image.
@@ -397,10 +416,10 @@ def display(self, image: Image):
397
416
A PIL.Image instance.
398
417
"""
399
418
if not image .size == (128 , 64 ):
400
- image .resize ((128 , 64 ))
419
+ image = image .resize ((128 , 64 ))
401
420
402
421
if not image .mode == "1" :
403
- image .convert ("1" )
422
+ image = image .convert ("1" )
404
423
405
424
image_data = image .getdata ()
406
425
pixels_per_page = self ._WIDTH * 8
@@ -411,17 +430,29 @@ def display(self, image: Image):
411
430
offsets = [y + self ._WIDTH * i for i in range (8 )]
412
431
413
432
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
+ )
423
443
424
444
buffer += list (buf )
425
445
426
446
self ._buffer = buffer
427
447
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