Skip to content

Commit 2e172a5

Browse files
Alex J LennonAlex J Lennon
Alex J Lennon
authored and
Alex J Lennon
committed
ssd1306oled: Add display of scrolling DoES logo
Signed-off-by: Alex J Lennon <Alex J Lennon>
1 parent 68b6001 commit 2e172a5

File tree

1 file changed

+248
-23
lines changed

1 file changed

+248
-23
lines changed

LoraOledESP32/ssd1306oled.ipynb

+248-23
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
"cells": [
33
{
44
"cell_type": "code",
5-
"execution_count": 1,
5+
"execution_count": 83,
66
"metadata": {},
77
"outputs": [
88
{
99
"name": "stdout",
1010
"output_type": "stream",
1111
"text": [
12-
"\u001b[34mConnecting to Serial /dev/ttyUSB2 baud=115200 \u001b[0m\n",
12+
"\u001b[34mConnecting to --port=/dev/ttyUSB0 --baud=115200 \u001b[0m\n",
1313
"\u001b[34mReady.\n",
1414
"\u001b[0m"
1515
]
@@ -21,27 +21,191 @@
2121
},
2222
{
2323
"cell_type": "code",
24-
"execution_count": 2,
24+
"execution_count": 10,
2525
"metadata": {},
2626
"outputs": [
2727
{
2828
"name": "stdout",
2929
"output_type": "stream",
3030
"text": [
31-
"Sent 168 lines (5477 bytes) to ssd1306.py.\n"
31+
"Sent 147 lines (4584 bytes) to ssd1306.py.\n"
3232
]
3333
}
3434
],
3535
"source": [
36-
"%sendtofile --source ssd1306.py\n"
36+
"%sendtofile ssd1306.py\n",
37+
"\n",
38+
"# MicroPython SSD1306 OLED driver, I2C and SPI interfaces\n",
39+
"\n",
40+
"from micropython import const\n",
41+
"import framebuf\n",
42+
"\n",
43+
"\n",
44+
"# register definitions\n",
45+
"SET_CONTRAST = const(0x81)\n",
46+
"SET_ENTIRE_ON = const(0xa4)\n",
47+
"SET_NORM_INV = const(0xa6)\n",
48+
"SET_DISP = const(0xae)\n",
49+
"SET_MEM_ADDR = const(0x20)\n",
50+
"SET_COL_ADDR = const(0x21)\n",
51+
"SET_PAGE_ADDR = const(0x22)\n",
52+
"SET_DISP_START_LINE = const(0x40)\n",
53+
"SET_SEG_REMAP = const(0xa0)\n",
54+
"SET_MUX_RATIO = const(0xa8)\n",
55+
"SET_COM_OUT_DIR = const(0xc0)\n",
56+
"SET_DISP_OFFSET = const(0xd3)\n",
57+
"SET_COM_PIN_CFG = const(0xda)\n",
58+
"SET_DISP_CLK_DIV = const(0xd5)\n",
59+
"SET_PRECHARGE = const(0xd9)\n",
60+
"SET_VCOM_DESEL = const(0xdb)\n",
61+
"SET_CHARGE_PUMP = const(0x8d)\n",
62+
"\n",
63+
"# Subclassing FrameBuffer provides support for graphics primitives\n",
64+
"# http://docs.micropython.org/en/latest/pyboard/library/framebuf.html\n",
65+
"class SSD1306(framebuf.FrameBuffer):\n",
66+
" def __init__(self, width, height, external_vcc):\n",
67+
" self.width = width\n",
68+
" self.height = height\n",
69+
" self.external_vcc = external_vcc\n",
70+
" self.pages = self.height // 8\n",
71+
" self.buffer = bytearray(self.pages * self.width)\n",
72+
" super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB)\n",
73+
" self.init_display()\n",
74+
"\n",
75+
" def init_display(self):\n",
76+
" for cmd in (\n",
77+
" SET_DISP | 0x00, # off\n",
78+
" # address setting\n",
79+
" SET_MEM_ADDR, 0x00, # horizontal\n",
80+
" # resolution and layout\n",
81+
" SET_DISP_START_LINE | 0x00,\n",
82+
" SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0\n",
83+
" SET_MUX_RATIO, self.height - 1,\n",
84+
" SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0\n",
85+
" SET_DISP_OFFSET, 0x00,\n",
86+
" SET_COM_PIN_CFG, 0x02 if self.height == 32 else 0x12,\n",
87+
" # timing and driving scheme\n",
88+
" SET_DISP_CLK_DIV, 0x80,\n",
89+
" SET_PRECHARGE, 0x22 if self.external_vcc else 0xf1,\n",
90+
" SET_VCOM_DESEL, 0x30, # 0.83*Vcc\n",
91+
" # display\n",
92+
" SET_CONTRAST, 0xff, # maximum\n",
93+
" SET_ENTIRE_ON, # output follows RAM contents\n",
94+
" SET_NORM_INV, # not inverted\n",
95+
" # charge pump\n",
96+
" SET_CHARGE_PUMP, 0x10 if self.external_vcc else 0x14,\n",
97+
" SET_DISP | 0x01): # on\n",
98+
" self.write_cmd(cmd)\n",
99+
" self.fill(0)\n",
100+
" self.show()\n",
101+
"\n",
102+
" def poweroff(self):\n",
103+
" self.write_cmd(SET_DISP | 0x00)\n",
104+
"\n",
105+
" def poweron(self):\n",
106+
" self.write_cmd(SET_DISP | 0x01)\n",
107+
"\n",
108+
" def contrast(self, contrast):\n",
109+
" self.write_cmd(SET_CONTRAST)\n",
110+
" self.write_cmd(contrast)\n",
111+
"\n",
112+
" def invert(self, invert):\n",
113+
" self.write_cmd(SET_NORM_INV | (invert & 1))\n",
114+
"\n",
115+
" def show(self):\n",
116+
" x0 = 0\n",
117+
" x1 = self.width - 1\n",
118+
" if self.width == 64:\n",
119+
" # displays with width of 64 pixels are shifted by 32\n",
120+
" x0 += 32\n",
121+
" x1 += 32\n",
122+
" self.write_cmd(SET_COL_ADDR)\n",
123+
" self.write_cmd(x0)\n",
124+
" self.write_cmd(x1)\n",
125+
" self.write_cmd(SET_PAGE_ADDR)\n",
126+
" self.write_cmd(0)\n",
127+
" self.write_cmd(self.pages - 1)\n",
128+
" self.write_data(self.buffer)\n",
129+
"\n",
130+
"\n",
131+
"class SSD1306_I2C(SSD1306):\n",
132+
" def __init__(self, width, height, i2c, addr=0x3c, external_vcc=False):\n",
133+
" self.i2c = i2c\n",
134+
" self.addr = addr\n",
135+
" self.temp = bytearray(2)\n",
136+
" super().__init__(width, height, external_vcc)\n",
137+
"\n",
138+
" def write_cmd(self, cmd):\n",
139+
" self.temp[0] = 0x80 # Co=1, D/C#=0\n",
140+
" self.temp[1] = cmd\n",
141+
" self.i2c.writeto(self.addr, self.temp)\n",
142+
"\n",
143+
" def write_data(self, buf):\n",
144+
" self.temp[0] = self.addr << 1\n",
145+
" self.temp[1] = 0x40 # Co=0, D/C#=1\n",
146+
" self.i2c.start()\n",
147+
" self.i2c.write(self.temp)\n",
148+
" self.i2c.write(buf)\n",
149+
" self.i2c.stop()\n",
150+
"\n",
151+
"\n",
152+
"class SSD1306_SPI(SSD1306):\n",
153+
" def __init__(self, width, height, spi, dc, res, cs, external_vcc=False):\n",
154+
" self.rate = 10 * 1024 * 1024\n",
155+
" dc.init(dc.OUT, value=0)\n",
156+
" res.init(res.OUT, value=0)\n",
157+
" cs.init(cs.OUT, value=1)\n",
158+
" self.spi = spi\n",
159+
" self.dc = dc\n",
160+
" self.res = res\n",
161+
" self.cs = cs\n",
162+
" import time\n",
163+
" self.res(1)\n",
164+
" time.sleep_ms(1)\n",
165+
" self.res(0)\n",
166+
" time.sleep_ms(10)\n",
167+
" self.res(1)\n",
168+
" super().__init__(width, height, external_vcc)\n",
169+
"\n",
170+
" def write_cmd(self, cmd):\n",
171+
" self.spi.init(baudrate=self.rate, polarity=0, phase=0)\n",
172+
" self.cs(1)\n",
173+
" self.dc(0)\n",
174+
" self.cs(0)\n",
175+
" self.spi.write(bytearray([cmd]))\n",
176+
" self.cs(1)\n",
177+
"\n",
178+
" def write_data(self, buf):\n",
179+
" self.spi.init(baudrate=self.rate, polarity=0, phase=0)\n",
180+
" self.cs(1)\n",
181+
" self.dc(1)\n",
182+
" self.cs(0)\n",
183+
" self.spi.write(buf)\n",
184+
" self.cs(1)"
37185
]
38186
},
39187
{
40188
"cell_type": "code",
41-
"execution_count": 3,
42-
"metadata": {
43-
"collapsed": true
44-
},
189+
"execution_count": 11,
190+
"metadata": {},
191+
"outputs": [
192+
{
193+
"name": "stdout",
194+
"output_type": "stream",
195+
"text": [
196+
"['boot.py', 'hmac.py', 'hotpie.py', 'ssd1306.py']\r\n"
197+
]
198+
}
199+
],
200+
"source": [
201+
"import os\n",
202+
"print(os.listdir())"
203+
]
204+
},
205+
{
206+
"cell_type": "code",
207+
"execution_count": 18,
208+
"metadata": {},
45209
"outputs": [],
46210
"source": [
47211
"#https://forum.micropython.org/viewtopic.php?f=18&p=23080\n",
@@ -53,6 +217,7 @@
53217
"scl = Pin(15, Pin.OUT, Pin.PULL_UP)\n",
54218
"sda = Pin(4, Pin.OUT, Pin.PULL_UP)\n",
55219
"i2c = I2C(scl=scl, sda=sda, freq=450000)\n",
220+
"\n",
56221
"o = ssd1306.SSD1306_I2C(128, 64, i2c, addr=0x3c)\n",
57222
"\n",
58223
"o.fill(0)\n",
@@ -63,14 +228,16 @@
63228
},
64229
{
65230
"cell_type": "code",
66-
"execution_count": 4,
231+
"execution_count": 80,
67232
"metadata": {},
68233
"outputs": [
69234
{
70-
"name": "stdout",
235+
"name": "stderr",
71236
"output_type": "stream",
72237
"text": [
73-
"[60]\r\n"
238+
"Traceback (most recent call last):\n",
239+
" File \"<stdin>\", line 1, in <module>\n",
240+
"NameError: name 'i2c' is not defined\n"
74241
]
75242
}
76243
],
@@ -80,12 +247,22 @@
80247
},
81248
{
82249
"cell_type": "code",
83-
"execution_count": 27,
84-
"metadata": {
85-
"collapsed": true
86-
},
87-
"outputs": [],
250+
"execution_count": 81,
251+
"metadata": {},
252+
"outputs": [
253+
{
254+
"name": "stderr",
255+
"output_type": "stream",
256+
"text": [
257+
"Traceback (most recent call last):\n",
258+
" File \"<stdin>\", line 3, in <module>\n",
259+
"NameError: name 'o' is not defined\n"
260+
]
261+
}
262+
],
88263
"source": [
264+
"import framebuf\n",
265+
"\n",
89266
"o.fill(0)\n",
90267
"for i in range(128):\n",
91268
" o.framebuf.fill_rect(1, 3, i, 34, 1)\n",
@@ -114,12 +291,60 @@
114291
},
115292
{
116293
"cell_type": "code",
117-
"execution_count": null,
118-
"metadata": {
119-
"collapsed": true
120-
},
121-
"outputs": [],
122-
"source": []
294+
"execution_count": 84,
295+
"metadata": {},
296+
"outputs": [
297+
{
298+
"name": "stdout",
299+
"output_type": "stream",
300+
"text": [
301+
".......\u001b[34m\n",
302+
"\n",
303+
"*** Sending Ctrl-C\n",
304+
"\n",
305+
"\u001b[0m"
306+
]
307+
},
308+
{
309+
"name": "stderr",
310+
"output_type": "stream",
311+
"text": [
312+
"Traceback (most recent call last):\n",
313+
" File \"<stdin>\", line 28, in <module>\n",
314+
"KeyboardInterrupt: \n"
315+
]
316+
}
317+
],
318+
"source": [
319+
"# Show the DoES logo. Scrolls across the screen\n",
320+
"\n",
321+
"import ssd1306\n",
322+
"import framebuf\n",
323+
"from machine import I2C, Pin\n",
324+
"rst = Pin(16, Pin.OUT)\n",
325+
"rst.value(1)\n",
326+
"scl = Pin(15, Pin.OUT, Pin.PULL_UP)\n",
327+
"sda = Pin(4, Pin.OUT, Pin.PULL_UP)\n",
328+
"i2c = I2C(scl=scl, sda=sda, freq=450000)\n",
329+
"display = ssd1306.SSD1306_I2C(128, 64, i2c, addr=0x3c)\n",
330+
"#o = ssd1306.SSD1306_I2C(128, 64, i2c, addr=0x3c)\n",
331+
"\n",
332+
"buffer = bytearray(\n",
333+
" b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xe7\\xe0\\x30\\x0f\\xff\\xf0\\x07\\x00\\xe0\\x30\\x03\\xff\\xf0\\x06\\x18\\xe0\\x31\\xe3\\xe1\\xf3\\xfe\\x3c\\xe0\\x31\\xf1\\xc0\\x73\\xfe\\x3f\\xe0\\x31\\xf1\\x8c\\x73\\xff\\x07\\xe0\\x31\\xf1\\x9e\\x30\\x07\\x80\\xe0\\x31\\xf1\\x1e\\x30\\x0f\\xf0\\x60\\x31\\xf1\\x1e\\x33\\xff\\xfc\\x60\\x31\\xf3\\x9e\\x33\\xfe\\x7e\\x60\\x31\\xc3\\x8e\\x73\\xfe\\x3c\\x60\\x30\\x07\\xc0\\x70\\x07\\x00\\xe0\\x30\\x1f\\xe1\\xf0\\x07\\x81\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x40\\x00\\x00\\x00\\x00\\x60\\x30\\x00\\x00\\x00\\x00\\x00\\x60\\x30\\x48\\x8c\\x15\\x86\\x0c\\x60\\x30\\x49\\xb6\\xe6\\xcd\\x9b\\x60\\x30\\x49\\xb2\\xc4\\x58\\xb3\\x60\\x30\\x4d\\x3e\\xc4\\x58\\xb3\\x60\\x30\\x47\\x30\\xc4\\x49\\xb3\\x60\\x3f\\x46\\x1e\\xc7\\xcf\\x1e\\x60\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n",
334+
")\n",
335+
"# FRAMEBUF_MHLSB = 3\n",
336+
"fb = framebuf.FrameBuffer(buffer, 56, 64,3)\n",
337+
"\n",
338+
"while True:\n",
339+
" for x in range(0,128-56):\n",
340+
" display.fill(0)\n",
341+
" display.blit(fb, x, 0)\n",
342+
" display.show()\n",
343+
" for x in range(0,128-56):\n",
344+
" display.fill(0)\n",
345+
" display.blit(fb, (128-56-x), 0)\n",
346+
" display.show()\n"
347+
]
123348
}
124349
],
125350
"metadata": {

0 commit comments

Comments
 (0)