22
22
"""
23
23
`adafruit_ssd1306`
24
24
====================================================
25
-
26
25
MicroPython SSD1306 OLED driver, I2C and SPI interfaces
27
-
28
26
* Author(s): Tony DiCola, Michael McWethy
29
27
"""
30
-
31
28
import time
32
-
33
29
from micropython import const
34
30
from adafruit_bus_device import i2c_device , spi_device
35
31
try :
36
32
import framebuf
37
33
except ImportError :
38
34
import adafruit_framebuf as framebuf
39
-
40
35
__version__ = "0.0.0-auto.0"
41
36
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_SSD1306.git"
42
-
43
37
#pylint: disable-msg=bad-whitespace
44
38
# register definitions
45
39
SET_CONTRAST = const (0x81 )
60
54
SET_VCOM_DESEL = const (0xdb )
61
55
SET_CHARGE_PUMP = const (0x8d )
62
56
#pylint: enable-msg=bad-whitespace
63
-
64
-
65
57
class _SSD1306 (framebuf .FrameBuffer ):
66
58
"""Base class for SSD1306 display driver"""
67
59
#pylint: disable-msg=too-many-arguments
@@ -81,12 +73,10 @@ def __init__(self, buffer, width, height, *, external_vcc, reset):
81
73
self ._power = False
82
74
self .poweron ()
83
75
self .init_display ()
84
-
85
76
@property
86
77
def power (self ):
87
78
"""True if the display is currently powered on, otherwise False"""
88
79
return self ._power
89
-
90
80
def init_display (self ):
91
81
"""Base class to initialize display"""
92
82
for cmd in (
@@ -95,14 +85,14 @@ def init_display(self):
95
85
SET_MEM_ADDR , 0x00 , # horizontal
96
86
# resolution and layout
97
87
SET_DISP_START_LINE | 0x00 ,
98
- SET_SEG_REMAP | 0x01 , # column addr 127 mapped to SEG0
88
+ SET_SEG_REMAP | 0x00 , # column addr 127 mapped to SEG0
99
89
SET_MUX_RATIO , self .height - 1 ,
100
90
SET_COM_OUT_DIR | 0x08 , # scan from COM[N] to COM0
101
91
SET_DISP_OFFSET , 0x00 ,
102
- SET_COM_PIN_CFG , 0x02 if self .height == 32 else 0x12 ,
92
+ SET_COM_PIN_CFG , 0x02 if self .height == 32 or self . height == 16 else 0x12 ,
103
93
# timing and driving scheme
104
94
SET_DISP_CLK_DIV , 0x80 ,
105
- SET_PRECHARGE , 0x22 if self .external_vcc else 0xf1 ,
95
+ SET_PRECHARGE , 0x22 if self .external_vcc else 0x22 ,
106
96
SET_VCOM_DESEL , 0x30 , # 0.83*Vcc
107
97
# display
108
98
SET_CONTRAST , 0xff , # maximum
@@ -112,31 +102,28 @@ def init_display(self):
112
102
SET_CHARGE_PUMP , 0x10 if self .external_vcc else 0x14 ,
113
103
SET_DISP | 0x01 ): # on
114
104
self .write_cmd (cmd )
105
+ if self .width == 72 :
106
+ self .write_cmd (0xAD )
107
+ self .write_cmd (0x30 )
115
108
self .fill (0 )
116
109
self .show ()
117
-
118
110
def poweroff (self ):
119
111
"""Turn off the display (nothing visible)"""
120
112
self .write_cmd (SET_DISP | 0x00 )
121
113
self ._power = False
122
-
123
114
def contrast (self , contrast ):
124
115
"""Adjust the contrast"""
125
116
self .write_cmd (SET_CONTRAST )
126
117
self .write_cmd (contrast )
127
-
128
118
def invert (self , invert ):
129
119
"""Invert all pixels on the display"""
130
120
self .write_cmd (SET_NORM_INV | (invert & 1 ))
131
-
132
121
def write_framebuf (self ):
133
122
"""Derived class must implement this"""
134
123
raise NotImplementedError
135
-
136
124
def write_cmd (self , cmd ):
137
125
"""Derived class must implement this"""
138
126
raise NotImplementedError
139
-
140
127
def poweron (self ):
141
128
"Reset device and turn on the display."
142
129
if self .reset_pin :
@@ -148,7 +135,6 @@ def poweron(self):
148
135
time .sleep (0.010 )
149
136
self .write_cmd (SET_DISP | 0x01 )
150
137
self ._power = True
151
-
152
138
def show (self ):
153
139
"""Update the display"""
154
140
xpos0 = 0
@@ -157,26 +143,27 @@ def show(self):
157
143
# displays with width of 64 pixels are shifted by 32
158
144
xpos0 += 32
159
145
xpos1 += 32
146
+ if self .width == 72 :
147
+ # displays with width of 72 pixels are shifted by 28
148
+ xpos0 += 28
149
+ xpos1 += 28
160
150
self .write_cmd (SET_COL_ADDR )
161
151
self .write_cmd (xpos0 )
162
152
self .write_cmd (xpos1 )
163
153
self .write_cmd (SET_PAGE_ADDR )
164
154
self .write_cmd (0 )
165
155
self .write_cmd (self .pages - 1 )
166
156
self .write_framebuf ()
167
-
168
157
class SSD1306_I2C (_SSD1306 ):
169
158
"""
170
159
I2C class for SSD1306
171
-
172
160
:param width: the width of the physical screen in pixels,
173
161
:param height: the height of the physical screen in pixels,
174
162
:param i2c: the I2C peripheral to use,
175
163
:param addr: the 8-bit bus address of the device,
176
164
:param external_vcc: whether external high-voltage source is connected.
177
165
:param reset: if needed, DigitalInOut designating reset pin
178
166
"""
179
-
180
167
def __init__ (self , width , height , i2c , * , addr = 0x3c , external_vcc = False , reset = None ):
181
168
self .i2c_device = i2c_device .I2CDevice (i2c , addr )
182
169
self .addr = addr
@@ -190,25 +177,21 @@ def __init__(self, width, height, i2c, *, addr=0x3c, external_vcc=False, reset=N
190
177
self .buffer [0 ] = 0x40 # Set first byte of data buffer to Co=0, D/C=1
191
178
super ().__init__ (memoryview (self .buffer )[1 :], width , height ,
192
179
external_vcc = external_vcc , reset = reset )
193
-
194
180
def write_cmd (self , cmd ):
195
181
"""Send a command to the SPI device"""
196
182
self .temp [0 ] = 0x80 # Co=1, D/C#=0
197
183
self .temp [1 ] = cmd
198
184
with self .i2c_device :
199
185
self .i2c_device .write (self .temp )
200
-
201
186
def write_framebuf (self ):
202
187
"""Blast out the frame buffer using a single I2C transaction to support
203
188
hardware I2C interfaces."""
204
189
with self .i2c_device :
205
190
self .i2c_device .write (self .buffer )
206
-
207
191
#pylint: disable-msg=too-many-arguments
208
192
class SSD1306_SPI (_SSD1306 ):
209
193
"""
210
194
SPI class for SSD1306
211
-
212
195
:param width: the width of the physical screen in pixels,
213
196
:param height: the height of the physical screen in pixels,
214
197
:param spi: the SPI peripheral to use,
@@ -228,15 +211,12 @@ def __init__(self, width, height, spi, dc, reset, cs, *,
228
211
self .buffer = bytearray ((height // 8 ) * width )
229
212
super ().__init__ (memoryview (self .buffer ), width , height ,
230
213
external_vcc = external_vcc , reset = reset )
231
-
232
214
def write_cmd (self , cmd ):
233
215
"""Send a command to the SPI device"""
234
216
self .dc_pin .value = 0
235
217
with self .spi_device as spi :
236
218
spi .write (bytearray ([cmd ]))
237
-
238
219
def write_framebuf (self ):
239
220
"""write to the frame buffer via SPI"""
240
221
self .dc_pin .value = 1
241
- with self .spi_device as spi :
242
- spi .write (self .buffer )
222
+ with self .spi_device as spi :
0 commit comments