Skip to content

Instantly share code, notes, and snippets.

@bryanjhv
Last active August 20, 2019 03:45
Show Gist options
  • Save bryanjhv/517a380806a3bd84ad3cad9ee17770c5 to your computer and use it in GitHub Desktop.
Save bryanjhv/517a380806a3bd84ad3cad9ee17770c5 to your computer and use it in GitHub Desktop.
Simplified Adafruit Python SSD1306 for Raspberry Pi 3B+ (I2C only)
from __future__ import division
from smbus import SMBus
SSD1306_ADDRESS = 0x3C
SSD1306_MEMORYMODE = 0x20
SSD1306_COLUMNADDR = 0x21
SSD1306_PAGEADDR = 0x22
SSD1306_SETCONTRAST = 0x81
SSD1306_CHARGEPUMP = 0x8D
SSD1306_SEGREMAP = 0xA0
SSD1306_DISPLAYALLON_RESUME = 0xA4
SSD1306_DISPLAYALLON = 0xA5 #< Not currently used
SSD1306_NORMALDISPLAY = 0xA6
SSD1306_INVERTDISPLAY = 0xA7
SSD1306_SETMULTIPLEX = 0xA8
SSD1306_DISPLAYOFF = 0xAE
SSD1306_DISPLAYON = 0xAF
SSD1306_COMSCANINC = 0xC0 #< Not currently used
SSD1306_COMSCANDEC = 0xC8
SSD1306_SETDISPLAYOFFSET = 0xD3
SSD1306_SETDISPLAYCLOCKDIV = 0xD5
SSD1306_SETPRECHARGE = 0xD9
SSD1306_SETCOMPINS = 0xDA
SSD1306_SETVCOMDETECT = 0xDB
SSD1306_SETLOWCOLUMN = 0x00 #< Not currently used
SSD1306_SETHIGHCOLUMN = 0x10 #< Not currently used
SSD1306_SETSTARTLINE = 0x40
SSD1306_EXTERNALVCC = 0x01 #< External display voltage source
SSD1306_SWITCHCAPVCC = 0x02 #< Gen. display voltage from 3.3V
SSD1306_RIGHT_HORIZONTAL_SCROLL = 0x26 #< Init rt scroll
SSD1306_LEFT_HORIZONTAL_SCROLL = 0x27 #< Init left scroll
SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL = 0x29 #< Init diag scroll
SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL = 0x2A #< Init diag scroll
SSD1306_DEACTIVATE_SCROLL = 0x2E #< Stop scroll
SSD1306_ACTIVATE_SCROLL = 0x2F #< Start scroll
SSD1306_SET_VERTICAL_SCROLL_AREA = 0xA3 #< Set scroll range
class SSD1306(object):
def __init__(self, width, height, address=SSD1306_ADDRESS):
self.width = width
self.height = height
self.address = address
self.bus = SMBus(1)
self.pages = height//8
self.clear()
def command(self, values):
try:
iter(values)
except TypeError:
values = [values]
finally:
for value in values:
self.bus.write_byte_data(self.address, 0x00, value)
def data(self, value):
try:
iter(values)
except TypeError:
values = [values]
finally:
for value in values:
self.bus.write_byte_data(self.address, 0x40, value)
def begin(self, vccstate=SSD1306_SWITCHCAPVCC):
self.vccstate = vccstate
self.initialize()
def display(self):
self.command([
SSD1306_PAGEADDR, 0x00, self.pages-1,
SSD1306_COLUMNADDR, 0x00, self.width-1,
])
for i in range(0, len(self.buffer), 16):
self.bus.write_i2c_block_data(self.address, 0x40, self.buffer[i:i+16])
def image(self, image):
if image.mode=='1':
imwidth, imheight = image.size
if imwidth==self.width and imheight==self.height:
pix = image.load()
index = 0
for page in range(self.pages):
for x in range(self.width):
bits = 0
for bit in [0,1,2,3,4,5,6,7]:
bits = bits << 1
bits |= 0 if pix[(x,page*8+7-bit)]==0 else 1
self.buffer[index] = bits
index += 1
def clear(self):
self.buffer = [0] * (self.width * self.pages)
def set_contrast(self, contrast):
self.command([
SSD1306_SETCONTRAST, contrast,
])
def initialize(self):
self.command([
SSD1306_DISPLAYOFF,
SSD1306_SETDISPLAYCLOCKDIV, 0x80,
SSD1306_SETMULTIPLEX, self.height-1,
])
self.command([
SSD1306_SETDISPLAYOFFSET, 0x00,
SSD1306_SETSTARTLINE|0x00,
SSD1306_CHARGEPUMP, 0x10 if self.vccstate==SSD1306_EXTERNALVCC else 0x14,
])
self.command([
SSD1306_MEMORYMODE, 0x00,
SSD1306_SEGREMAP|0x01,
SSD1306_COMSCANDEC,
])
if self.width==128 and self.height==64:
self.command([
SSD1306_SETCOMPINS, 0x12,
SSD1306_SETCONTRAST, 0x9F if self.vccstate==SSD1306_EXTERNALVCC else 0xCF,
])
elif self.width==128 and self.height==32:
self.command([
SSD1306_SETCOMPINS, 0x02,
SSD1306_SETCONTRAST, 0x8F,
])
elif self.width==96 and self.height==16:
self.command([
SSD1306_SETCOMPINS, 0x02,
SSD1306_SETCONTRAST, 0x10 if self.vccstate==SSD1306_EXTERNALVCC else 0xAF,
])
else:
# TODO: map other screens
pass
self.command([
SSD1306_SETPRECHARGE, 0x22 if self.vccstate==SSD1306_EXTERNALVCC else 0xF1,
])
self.command([
SSD1306_SETVCOMDETECT, 0x40,
SSD1306_DISPLAYALLON_RESUME, SSD1306_NORMALDISPLAY,
SSD1306_DEACTIVATE_SCROLL,
SSD1306_DISPLAYON,
])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment