from micropython import const
import framebuf
from machine import Pin, I2C
# Minimal SSD1306 driver
_SET_CONTRAST = const(0x81)
_SET_ENTIRE_ON = const(0xA4)
_SET_NORM_INV = const(0xA6)
_SET_DISP = const(0xAE)
_SET_MEM_ADDR = const(0x20)
_SET_COL_ADDR = const(0x21)
_SET_PAGE_ADDR = const(0x22)
_SET_DISP_START_LINE = const(0x40)
_SET_SEG_REMAP = const(0xA0)
_SET_MUX_RATIO = const(0xA8)
_SET_COM_OUT_DIR = const(0xC0)
_SET_DISP_OFFSET = const(0xD3)
_SET_COM_PIN_CFG = const(0xDA)
_SET_DISP_CLK_DIV = const(0xD5)
_SET_PRECHARGE = const(0xD9)
_SET_VCOM_DESEL = const(0xDB)
_SET_CHARGE_PUMP = const(0x8D)
class SSD1306:
def __init__(self, width, height, external_vcc):
self.width = width
self.height = height
self.external_vcc = external_vcc
self.pages = height // 8
self.buffer = bytearray(self.pages * width)
self.framebuf = framebuf.FrameBuffer(
self.buffer, width, height, framebuf.MONO_VLSB
)
self.init_display()
def init_display(self):
for cmd in (
_SET_DISP | 0x00, # off
_SET_DISP_CLK_DIV, 0x80,
_SET_MUX_RATIO, self.height - 1,
_SET_DISP_OFFSET, 0x00,
_SET_DISP_START_LINE | 0x00,
_SET_CHARGE_PUMP, 0x10 if self.external_vcc else 0x14,
_SET_MEM_ADDR, 0x00,
_SET_SEG_REMAP | 0x01,
_SET_COM_OUT_DIR | 0x08,
_SET_COM_PIN_CFG, 0x02 if self.height == 32 else 0x12,
_SET_CONTRAST, 0x9F,
_SET_PRECHARGE, 0x22 if self.external_vcc else 0xF1,
_SET_VCOM_DESEL, 0x30,
_SET_ENTIRE_ON,
_SET_NORM_INV,
_SET_DISP | 0x01, # on
):
self.write_cmd(cmd)
self.fill(0)
self.show()
def write_cmd(self, cmd):
raise NotImplementedError
def fill(self, col):
self.framebuf.fill(col)
def pixel(self, x, y, col):
self.framebuf.pixel(x, y, col)
def text(self, string, x, y, col=1):
self.framebuf.text(string, x, y, col)
def rect(self, x, y, w, h, col):
self.framebuf.rect(x, y, w, h, col)
def show(self):
x0 = 0
x1 = self.width - 1
self.write_cmd(_SET_COL_ADDR)
self.write_cmd(x0)
self.write_cmd(x1)
self.write_cmd(_SET_PAGE_ADDR)
self.write_cmd(0)
self.write_cmd(self.pages - 1)
self.write_data(self.buffer)
class SSD1306_I2C(SSD1306):
def __init__(self, width, height, i2c, addr=0x3C, external_vcc=False):
self.i2c = i2c
self.addr = addr
self.temp = bytearray(2)
super().__init__(width, height, external_vcc)
def write_cmd(self, cmd):
self.temp[0] = 0x80 # Co=1, D/C#=0
self.temp[1] = cmd
self.i2c.writeto(self.addr, self.temp)
def write_data(self, buf):
self.temp[0] = self.addr
self.temp[1] = 0x40 # Co=0, D/C#=1
self.i2c.start()
self.i2c.write(self.temp)
self.i2c.write(buf)
self.i2c.stop()
# Your original code
i2c = I2C(0, sda=Pin(21, pull=Pin.PULL_UP),
scl=Pin(22, pull=Pin.PULL_UP))
oled = SSD1306_I2C(128, 64, i2c)
oled.fill(0)
oled.rect(0, 0, 127, 63, 1)
oled.text('PROGRAMMING the', 5, 12, 1)
oled.text('ESP32', 5, 22, 1)
oled.text('by', 5, 32, 1)
oled.text('Simon Monk', 5, 42, 1)
oled.show()