-
Notifications
You must be signed in to change notification settings - Fork 4
/
adafruit_displayio_sh1106.py
127 lines (104 loc) · 4.15 KB
/
adafruit_displayio_sh1106.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
# SPDX-FileCopyrightText: Copyright (c) 2021 ladyada for Adafruit Industries
#
# SPDX-License-Identifier: MIT
"""
`adafruit_displayio_sh1106`
================================================================================
DisplayIO compatible library for SH1106 OLED displays
* Author(s): ladyada
Implementation Notes
--------------------
**Hardware:**
**Software and Dependencies:**
* Adafruit CircuitPython firmware for the supported boards:
https://github.com/adafruit/circuitpython/releases
"""
# Support both 8.x.x and 9.x.x. Change when 8.x.x is discontinued as a stable release.
try:
from typing import Union
except ImportError:
pass
try:
from fourwire import FourWire
from busdisplay import BusDisplay
from i2cdisplaybus import I2CDisplayBus
except ImportError:
from displayio import FourWire
from displayio import I2CDisplay as I2CDisplayBus
from displayio import Display as BusDisplay
__version__ = "0.0.0+auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_DisplayIO_SH1106.git"
# Sequence from sh1106 framebuf driver formatted for displayio init
_INIT_SEQUENCE = (
b"\xae\x00" # display off, sleep mode
b"\xd5\x01\x80" # divide ratio/oscillator: divide by 2, fOsc (POR)
b"\xa8\x01\x3f" # multiplex ratio = 64 (POR)
b"\xd3\x01\x00" # set display offset mode = 0x0
b"\x40\x00" # set start line
b"\xad\x01\x8b" # turn on DC/DC
b"\xa1\x00" # segment remap = 1 (POR=0, down rotation)
b"\xc8\x00" # scan decrement
b"\xda\x01\x12" # set com pins
b"\x81\x01\xff" # contrast setting = 0xff
b"\xd9\x01\x1f" # pre-charge/dis-charge period mode: 2 DCLKs/2 DCLKs (POR)
b"\xdb\x01\x40" # VCOM deselect level = 0.770 (POR)
b"\x20\x01\x20" #
b"\x33\x00" # turn on VPP to 9V
b"\xa6\x00" # normal (not reversed) display
b"\xa4\x00" # entire display off, retain RAM, normal status (POR)
b"\xaf\x00" # DISPLAY_ON
)
class SH1106(BusDisplay):
"""
SH1106 driver for use with displayio
:param bus: The bus that the display is connected to.
:param int width: The width of the display. Maximum of 132
:param int height: The height of the display. Maximum of 64
:param int rotation: The rotation of the display. 0, 90, 180 or 270.
"""
def __init__(self, bus: Union[FourWire, I2CDisplayBus], **kwargs) -> None:
init_sequence = bytearray(_INIT_SEQUENCE)
super().__init__(
bus,
init_sequence,
**kwargs,
color_depth=1,
grayscale=True,
pixels_in_byte_share_row=False, # in vertical (column) mode
data_as_commands=True, # every byte will have a command byte preceeding
brightness_command=0x81,
single_byte_bounds=True,
# for sh1107 use column and page addressing.
# lower column command = 0x00 - 0x0F
# upper column command = 0x10 - 0x17
# set page address = 0xB0 - 0xBF (16 pages)
SH1107_addressing=True,
)
self._is_awake = True # Display starts in active state (_INIT_SEQUENCE)
@property
def is_awake(self) -> bool:
"""
The power state of the display. (read-only)
`True` if the display is active, `False` if in sleep mode.
"""
return self._is_awake
def sleep(self) -> None:
"""
Put display into sleep mode. The display uses < 5uA in sleep mode.
Sleep mode does the following:
1) Stops the oscillator and DC-DC circuits
2) Stops the OLED drive
3) Remembers display data and operation mode active prior to sleeping
4) The MP can access (update) the built-in display RAM
"""
if self._is_awake:
self.bus.send(0xAE, []) # 0xAE = display off, sleep mode
self._is_awake = False
def wake(self) -> None:
"""
Wake display from sleep mode
"""
if not self._is_awake:
self.bus.send(0xAF, []) # 0xAF = display on
self._is_awake = True