Skip to content

Instantly share code, notes, and snippets.

@jimmo
Created January 10, 2017 23:52
Show Gist options
  • Save jimmo/37b2de125fe3dbd2c76be8c0711dd36f to your computer and use it in GitHub Desktop.
Save jimmo/37b2de125fe3dbd2c76be8c0711dd36f to your computer and use it in GitHub Desktop.
OLED driver for the micro:bit
from microbit import *
import ustruct
def color565(r, g, b):
return (r & 0xf8) << 8 | (g & 0xfc) << 3 | b >> 3
class Display:
_INIT = (
(0xFD, b'\x12'), (0xFD, b'\xb1'), (0xAE, b''), (0xB2, b'\xa4\x00\x00'), (0xB3, b'\xf0'), (0xCA, b'\x7f'), (0xA0, b'\x74'), (0xA1, b'\x00'), (0xA2, b'\x00'), (0xB5, b'\x00'), (0xAB, b'\x01'), (0xB1, b'\x32'), (0xBB, b'\x1f'), (0xBE, b'\x05'), (0xA6, b''), (0xC1, b'\xc8\x80\xc8'), (0xC7, b'\x0a'), (0xB4, b'\xa0\xb5\x55'), (0xB6, b'\x01'), (0xAF, b''),
)
def __init__(self):
spi.init(baudrate=2000000)
pin0.write_digital(1) # cs
pin1.write_digital(0) # dc
pin2.write_digital(0) # rst
self.reset()
for command, data in self._INIT:
self._write(command, data)
def _block(self, x0, y0, x1, y1, data=None):
self._write(0x15, self._encode_pos(x0, x1))
self._write(0x75, self._encode_pos(y0, y1))
if data is None:
size = ustruct.calcsize(">BBB")
return self._read(0x5D, (x1 - x0 + 1) * (y1 - y0 + 1) * size)
self._write(0x5C, data)
def _encode_pos(self, a, b):
return ustruct.pack(">BB", a, b)
def _encode_pixel(self, color):
return ustruct.pack(">H", color)
def _decode_pixel(self, data):
return color565(*ustruct.unpack(">BBB", data))
def pixel(self, x, y, color=None):
if color is None:
return self._decode_pixel(self._block(x, y, x, y))
if not 0 <= x < 128 or not 0 <= y < 128:
return
self._block(x, y, x, y, self._encode_pixel(color))
def fill_rectangle(self, x, y, w, h, color):
x = min(128 - 1, max(0, x))
y = min(128 - 1, max(0, y))
w = min(128 - x, max(1, w))
h = min(128 - y, max(1, h))
self._block(x, y, x + w - 1, y + h - 1, b'')
chunks, rest = divmod(w * h, 512)
pixel = self._encode_pixel(color)
if chunks:
data = pixel * 32
for i in range(16):
for count in range(chunks):
self._write(None, data)
self._write(None, pixel * rest)
def fill(self, color=0):
self.fill_rectangle(0, 0, 128, 128, color)
def hline(self, x, y, w, color):
self.fill_rectangle(x, y, w, 1, color)
def vline(self, x, y, h, color):
self.fill_rectangle(x, y, 1, h, color)
def reset(self):
pin2.write_digital(0)
sleep(50)
pin2.write_digital(1)
sleep(50)
def _write(self, command=None, data=None):
if command is not None:
pin1.write_digital(0)
pin0.write_digital(0)
spi.write(bytearray([command]))
pin0.write_digital(1)
if data is not None:
pin1.write_digital(1)
pin0.write_digital(0)
spi.write(data)
pin0.write_digital(1)
def _read(self, command=None, count=0):
pin1.write_digital(0)
pin0.write_digital(0)
if command is not None:
spi.write(bytearray([command]))
if count:
data = spi.read(count)
pin0.write_digital(1)
return data
d = Display()
d.fill(color565(0, 0, 0))
for i in range(1, 16):
d.hline(0, i * 8, 128, color565(255, 0, 0))
for i in range(1, 16):
d.vline(i * 8, 0, 128, color565(0, 255, 0))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment