Skip to content

Commit e2c5273

Browse files
committed
Update oled.py
add width/height parameter, support 128x64/128x32 etc.
1 parent 814bf7f commit e2c5273

File tree

1 file changed

+113
-75
lines changed

1 file changed

+113
-75
lines changed

‎LED/OLED_I2C_ASC/oled.py‎

Lines changed: 113 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,27 @@
77
https://www.micropython.org.cn
88
99
'''
10-
11-
cmd = [
12-
[0xAE],
13-
[0xA4],
14-
[0xD5, 0xF0],
15-
[0xA8, 0x3F],
16-
[0xD3, 0x00],
17-
[0 | 0x0],
18-
[0x8D, 0x14],
19-
[0x20, 0x00],
20-
[0x21, 0, 127],
21-
[0x22, 0, 63],
22-
[0xa0 | 0x1],
23-
[0xc8],
24-
[0xDA, 0x12],
25-
[0x81, 0xCF],
26-
[0xd9, 0xF1],
27-
[0xDB, 0x40],
28-
[0xA6],
29-
[0xd6, 0],
30-
[0xaf]
31-
]
10+
from micropython import const
11+
12+
# register definitions
13+
SET_CONTRAST = const(0x81)
14+
SET_ENTIRE_ON = const(0xA4)
15+
SET_NORM_INV = const(0xA6)
16+
SET_DISP = const(0xAE)
17+
SET_MEM_ADDR = const(0x20)
18+
SET_COL_ADDR = const(0x21)
19+
SET_PAGE_ADDR = const(0x22)
20+
SET_DISP_START_LINE = const(0x40)
21+
SET_SEG_REMAP = const(0xA0)
22+
SET_MUX_RATIO = const(0xA8)
23+
SET_IREF_SELECT = const(0xAD)
24+
SET_COM_OUT_DIR = const(0xC0)
25+
SET_DISP_OFFSET = const(0xD3)
26+
SET_COM_PIN_CFG = const(0xDA)
27+
SET_DISP_CLK_DIV = const(0xD5)
28+
SET_PRECHARGE = const(0xD9)
29+
SET_VCOM_DESEL = const(0xDB)
30+
SET_CHARGE_PUMP = const(0x8D)
3231

3332
from Font_6x8 import Font_6x8
3433
from Font_8x16 import Font_8x16
@@ -40,72 +39,109 @@
4039
Font_12_24 = const(3)
4140
Font_16_32 = const(4)
4241

43-
OLED_ADDR = 0x3C
44-
screen = bytearray(1025)
45-
screen[0] = 0x40
42+
OLED_ADDR = const(0x3C)
4643

47-
class OLED12864_I2C():
48-
def __init__(self, i2c, ADDR = OLED_ADDR):
44+
class OLED_I2C():
45+
def __init__(self, i2c, width=128, height=64, ADDR = OLED_ADDR, external_vcc=False):
46+
self.temp = bytearray(2)
47+
self.external_vcc = external_vcc
4948
self.px = 0
5049
self.py = 0
51-
self.width = 128
52-
self.height = 64
53-
self.MAX_X = 127
54-
self.MAX_Y = 63
50+
self.width = width
51+
self.height = height
52+
self.MAX_X = width-1
53+
self.MAX_Y = height-1
5554
self.i2c = i2c
55+
self.screen = bytearray(width*height//8 + 1)
56+
self.screen[0] = 0x40
5657
self._DRAW = 1
5758
self._sav = 0
5859
self.ADDR = ADDR
5960
self.Font(1)
60-
for c in cmd:
61-
self.command(c)
61+
for cmd in (
62+
SET_DISP, # display off
63+
# address setting
64+
SET_MEM_ADDR,
65+
0x00, # horizontal
66+
# resolution and layout
67+
SET_DISP_START_LINE, # start at line 0
68+
SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0
69+
SET_MUX_RATIO,
70+
self.height - 1,
71+
SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0
72+
SET_DISP_OFFSET,
73+
0x00,
74+
SET_COM_PIN_CFG,
75+
0x02 if self.width > 2 * self.height else 0x12,
76+
# timing and driving scheme
77+
SET_DISP_CLK_DIV,
78+
0x80,
79+
SET_PRECHARGE,
80+
0x22 if self.external_vcc else 0xF1,
81+
SET_VCOM_DESEL,
82+
0x30, # 0.83*Vcc
83+
# display
84+
SET_CONTRAST,
85+
0xFF, # maximum
86+
SET_ENTIRE_ON, # output follows RAM contents
87+
SET_NORM_INV, # not inverted
88+
SET_IREF_SELECT,
89+
0x30, # enable internal IREF during display on
90+
# charge pump
91+
SET_CHARGE_PUMP,
92+
0x10 if self.external_vcc else 0x14,
93+
SET_DISP | 0x01, # display on
94+
): # on
95+
self.command(cmd)
6296
self.clear()
6397

64-
def command(self, c):
65-
self.i2c.writeto(self.ADDR, b'\x00' + bytearray(c))
98+
def command(self, cmd):
99+
self.temp[0] = 0x80 # Co=1, D/C#=0
100+
self.temp[1] = cmd
101+
self.i2c.writeto(self.ADDR, self.temp)
66102

67103
def set_pos(self, col=0, page=0):
68-
self.command([0xb0 | page])
104+
self.command(0xb0 | page)
69105
c1, c2 = col & 0x0F, col >> 4
70-
self.command([0x00 | c1])
71-
self.command([0x10 | c2])
106+
self.command(0x00 | c1)
107+
self.command(0x10 | c2)
72108

73109
def pixel(self, x, y, color=1):
74110
if x<0 or x>self.MAX_X or y<0 or y>self.MAX_Y:
75111
return
76112
page, shift_page = divmod(y, 8)
77113
ind = x + page * 128 + 1
78-
b = screen[ind] | (1 << shift_page) if color else screen[ind] & ~ (1 << shift_page)
79-
screen[ind] = b
114+
b = self.screen[ind] | (1 << shift_page) if color else self.screen[ind] & ~ (1 << shift_page)
115+
self.screen[ind] = b
80116
if self._DRAW:
81117
self.set_pos(x, page)
82118
self.i2c.writeto(self.ADDR, bytearray([0x40, b]))
83119

84120
def invert(self, v=1):
85121
n = 0xa7 if v else 0xa6
86-
self.command([n])
122+
self.command(n)
87123

88124
def on(self, v = 1):
89125
d = 0xAF if v else 0xAE
90-
self.command([d])
126+
self.command(d)
91127

92128
def clear(self, c=0):
93-
for i in range(1, 1025):
94-
screen[i] = 0
129+
for i in range(1, len(self.screen)):
130+
self.screen[i] = 0
95131
self.draw()
96132

97133
def draw(self):
98134
if self._DRAW:
99135
self.set_pos()
100-
self.i2c.writeto(self.ADDR, screen)
136+
self.i2c.writeto(self.ADDR, self.screen)
101137

102138
def zoom(self, z=1):
103-
d = 1 if z else 0
104-
self.command([0xD6,d])
139+
self.command(0xD6)
140+
self.command(1 if z else 0)
105141

106142
def rotate(self, rotate=1):
107-
self.command([0xC0 | ((rotate & 1) << 3)])
108-
self.command([0xA0 | (rotate & 1)])
143+
self.command(0xC0 | ((rotate & 1) << 3))
144+
self.command(0xA0 | (rotate & 1))
109145

110146
def line(self, x1, y1, x2, y2, c=1):
111147
return
@@ -149,54 +185,56 @@ def font(self, FONT):
149185
def scroll(self):
150186
self.px = 0
151187
self.py += 1
152-
if self.py > 7:
153-
self.py = 7
154-
for i in range(1, 897):
155-
screen[i] = screen[i+128]
156-
for i in range(128):
157-
screen[-i-1] = 0
188+
if self.py > (self.height//8-1):
189+
self.py = self.height//8-1
190+
for i in range(1, len(self.screen)-self.width):
191+
self.screen[i] = self.screen[i+self.width]
192+
for i in range(self.width):
193+
self.screen[-i-1] = 0
158194
self.draw()
159195

160196
def char_6x8(self, x=0, y=0, ch=32, c=1):
161197
try:
162-
ind = x + y * 128 + 1
198+
ind = x + y * self.width + 1
163199
n = (min(127, max(ord(ch), 32)) -32)*5
164200
for i in range(5):
165-
screen[ind+i] = Font_6x8[n+i] if c else Font_6x8[n+i]^0xFF
166-
screen[ind+5] = 0 if c else 0xFF
201+
self.screen[ind+i] = Font_6x8[n+i] if c else Font_6x8[n+i]^0xFF
202+
self.screen[ind+5] = 0 if c else 0xFF
167203
self.set_pos(x, y)
168-
self.i2c.writeto(self.ADDR, b'\x40' + screen[ind:ind + 6])
204+
self.i2c.writeto(self.ADDR, b'\x40' + self.screen[ind:ind + 6])
169205
except:
170206
return
171207

172208
def text_6x8(self, x=0, y=0, s='', c=1, wrap=0):
173209
for i in range(len(s)):
174210
self.char(x, y, s[i], c)
175211
x += 6
176-
if wrap and x > 120:
212+
if wrap and (x > self.width-6):
177213
x = 0
178214
y += 1
179215

180216
def print(self, s, c = 1, cr = 1):
217+
if type(s) != str:
218+
s = str(s)
181219
for i in range(len(s)):
182220
self.char_6x8(self.px, self.py, s[i], c)
183221
self.px += 6
184-
if self.px > 120:
222+
if self.px > self.width-6:
185223
self.scroll()
186224
if cr:
187225
self.scroll()
188226

189227
def char_8x16(self, x=0, y=0, ch=32, c=1):
190228
try:
191-
ind = x + y * 128 + 1
229+
ind = x + y * self.width + 1
192230
n = (min(127, max(ord(ch), 32)) -32)*14
193231
for j in range(2):
194-
ind = x + y * 128 + 1
232+
ind = x + y * self.width + 1
195233
for i in range(7):
196-
screen[ind+i] = Font_8x16[n+i] if c else Font_8x16[n+i]^0xFF
197-
screen[ind+7] = 0 if c else 0xFF
234+
self.screen[ind+i] = Font_8x16[n+i] if c else Font_8x16[n+i]^0xFF
235+
self.screen[ind+7] = 0 if c else 0xFF
198236
self.set_pos(x, y)
199-
self.i2c.writeto(self.ADDR, b'\x40' + screen[ind:ind + 8])
237+
self.i2c.writeto(self.ADDR, b'\x40' + self.screen[ind:ind + 8])
200238
y += 1
201239
n += 7
202240
except:
@@ -206,19 +244,19 @@ def text_8x16(self, x=0, y=0, s='', c=1, wrap=0):
206244
for i in range(len(s)):
207245
self.char_8x16(x, y, s[i], c)
208246
x += 8
209-
if wrap and x > 120:
247+
if wrap and (x > self.width-8):
210248
x = 0
211249
y += 2
212250

213251
def char_12x24(self, x=0, y=0, ch=32, c=1):
214252
try:
215253
n = (min(127, max(ord(ch), 32)) -32)*36
216254
for j in range(3):
217-
ind = x + y * 128 + 1
255+
ind = x + y * self.width + 1
218256
for i in range(12):
219-
screen[ind+i] = Font_12x24[n+i] if c else Font_12x24[n+i]^0xFF
257+
self.screen[ind+i] = Font_12x24[n+i] if c else Font_12x24[n+i]^0xFF
220258
self.set_pos(x, y)
221-
self.i2c.writeto(self.ADDR, b'\x40' + screen[ind:ind + 12])
259+
self.i2c.writeto(self.ADDR, b'\x40' + self.screen[ind:ind + 12])
222260
y += 1
223261
n += 12
224262
except:
@@ -228,19 +266,19 @@ def text_12x24(self, x=0, y=0, s='', c=1, wrap=0):
228266
for i in range(len(s)):
229267
self.char_12x24(x, y, s[i], c)
230268
x += 12
231-
if wrap and x > 116:
269+
if wrap and (x > self.width-12):
232270
x = 0
233271
y += 3
234272

235273
def char_16x32(self, x=0, y=0, ch=32, c=1):
236274
try:
237275
n = (min(127, max(ord(ch), 32)) -32)*64
238276
for j in range(4):
239-
ind = x + y * 128 + 1
277+
ind = x + y * self.width + 1
240278
for i in range(16):
241-
screen[ind+i] = Font_16x32[n+i] if c else Font_16x32[n+i]^0xFF
279+
self.screen[ind+i] = Font_16x32[n+i] if c else Font_16x32[n+i]^0xFF
242280
self.set_pos(x, y)
243-
self.i2c.writeto(self.ADDR, b'\x40' + screen[ind:ind + 16])
281+
self.i2c.writeto(self.ADDR, b'\x40' + self.screen[ind:ind + 16])
244282
y += 1
245283
n += 16
246284
except:
@@ -250,7 +288,7 @@ def text_16x32(self, x=0, y=0, s='', c=1, wrap=0):
250288
for i in range(len(s)):
251289
self.char_16x32(x, y, s[i], c)
252290
x += 16
253-
if wrap and x > 112:
291+
if wrap and (x > self.width-16):
254292
x = 0
255293
y += 4
256294

0 commit comments

Comments
 (0)