summaryrefslogtreecommitdiff
path: root/drivers/display
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/display')
-rw-r--r--drivers/display/lcd160cr.py474
-rw-r--r--drivers/display/lcd160cr_test.py171
-rw-r--r--drivers/display/ssd1306.py160
3 files changed, 0 insertions, 805 deletions
diff --git a/drivers/display/lcd160cr.py b/drivers/display/lcd160cr.py
deleted file mode 100644
index dd9ab9985..000000000
--- a/drivers/display/lcd160cr.py
+++ /dev/null
@@ -1,474 +0,0 @@
-# Driver for official MicroPython LCD160CR display
-# MIT license; Copyright (c) 2017 Damien P. George
-
-from micropython import const
-from utime import sleep_ms
-from ustruct import calcsize, pack_into
-import uerrno, machine
-
-# for set_orient
-PORTRAIT = const(0)
-LANDSCAPE = const(1)
-PORTRAIT_UPSIDEDOWN = const(2)
-LANDSCAPE_UPSIDEDOWN = const(3)
-
-# for set_startup_deco; can be or'd
-STARTUP_DECO_NONE = const(0)
-STARTUP_DECO_MLOGO = const(1)
-STARTUP_DECO_INFO = const(2)
-
-_uart_baud_table = {
- 2400: 0,
- 4800: 1,
- 9600: 2,
- 19200: 3,
- 38400: 4,
- 57600: 5,
- 115200: 6,
- 230400: 7,
- 460800: 8,
-}
-
-class LCD160CR:
- def __init__(self, connect=None, *, pwr=None, i2c=None, spi=None, i2c_addr=98):
- if connect in ('X', 'Y', 'XY', 'YX'):
- i = connect[-1]
- j = connect[0]
- y = j + '4'
- elif connect == 'C':
- i = 2
- j = 2
- y = 'A7'
- else:
- if pwr is None or i2c is None or spi is None:
- raise ValueError('must specify valid "connect" or all of "pwr", "i2c" and "spi"')
-
- if pwr is None:
- pwr = machine.Pin(y, machine.Pin.OUT)
- if i2c is None:
- i2c = machine.I2C(i, freq=1000000)
- if spi is None:
- spi = machine.SPI(j, baudrate=13500000, polarity=0, phase=0)
-
- if not pwr.value():
- pwr(1)
- sleep_ms(10)
- # else:
- # alread have power
- # lets be optimistic...
-
- # set connections
- self.pwr = pwr
- self.i2c = i2c
- self.spi = spi
- self.i2c_addr = i2c_addr
-
- # create temp buffers and memoryviews
- self.buf16 = bytearray(16)
- self.buf19 = bytearray(19)
- self.buf = [None] * 10
- for i in range(1, 10):
- self.buf[i] = memoryview(self.buf16)[0:i]
- self.buf1 = self.buf[1]
- self.array4 = [0, 0, 0, 0]
-
- # set default orientation and window
- self.set_orient(PORTRAIT)
- self._fcmd2b('<BBBBBB', 0x76, 0, 0, self.w, self.h) # viewport 'v'
- self._fcmd2b('<BBBBBB', 0x79, 0, 0, self.w, self.h) # window 'y'
-
- def _send(self, cmd):
- i = self.i2c.writeto(self.i2c_addr, cmd)
- if i == len(cmd):
- return
- cmd = memoryview(cmd)
- n = len(cmd)
- while True:
- i += self.i2c.writeto(self.i2c_addr, cmd[i:])
- if i == n:
- return
- sleep_ms(10)
-
- def _fcmd2(self, fmt, a0, a1=0, a2=0):
- buf = self.buf[calcsize(fmt)]
- pack_into(fmt, buf, 0, 2, a0, a1, a2)
- self._send(buf)
-
- def _fcmd2b(self, fmt, a0, a1, a2, a3, a4=0):
- buf = self.buf[calcsize(fmt)]
- pack_into(fmt, buf, 0, 2, a0, a1, a2, a3, a4)
- self._send(buf)
-
- def _waitfor(self, n, buf):
- t = 5000
- while t:
- self.i2c.readfrom_into(self.i2c_addr, self.buf1)
- if self.buf1[0] >= n:
- self.i2c.readfrom_into(self.i2c_addr, buf)
- return
- t -= 1
- sleep_ms(1)
- raise OSError(uerrno.ETIMEDOUT)
-
- def oflush(self, n=255):
- t = 5000
- while t:
- self.i2c.readfrom_into(self.i2c_addr + 1, self.buf1)
- r = self.buf1[0]
- if r >= n:
- return
- t -= 1
- machine.idle()
- raise OSError(uerrno.ETIMEDOUT)
-
- def iflush(self):
- t = 5000
- while t:
- self.i2c.readfrom_into(self.i2c_addr, self.buf16)
- if self.buf16[0] == 0:
- return
- t -= 1
- sleep_ms(1)
- raise OSError(uerrno.ETIMEDOUT)
-
- #### MISC METHODS ####
-
- @staticmethod
- def rgb(r, g, b):
- return ((b & 0xf8) << 8) | ((g & 0xfc) << 3) | (r >> 3)
-
- @staticmethod
- def clip_line(c, w, h):
- while True:
- ca = ce = 0
- if c[1] < 0:
- ca |= 8
- elif c[1] > h:
- ca |= 4
- if c[0] < 0:
- ca |= 1
- elif c[0] > w:
- ca |= 2
- if c[3] < 0:
- ce |= 8
- elif c[3] > h:
- ce |= 4
- if c[2] < 0:
- ce |= 1
- elif c[2] > w:
- ce |= 2
- if ca & ce:
- return False
- elif ca | ce:
- ca |= ce
- if ca & 1:
- if c[2] < c[0]:
- c[0], c[2] = c[2], c[0]
- c[1], c[3] = c[3], c[1]
- c[1] += ((-c[0]) * (c[3] - c[1])) // (c[2] - c[0])
- c[0] = 0
- elif ca & 2:
- if c[2] < c[0]:
- c[0], c[2] = c[2], c[0]
- c[1], c[3] = c[3], c[1]
- c[3] += ((w - 1 - c[2]) * (c[3] - c[1])) // (c[2] - c[0])
- c[2] = w - 1
- elif ca & 4:
- if c[0] == c[2]:
- if c[1] >= h:
- c[1] = h - 1
- if c[3] >= h:
- c[3] = h - 1
- else:
- if c[3] < c[1]:
- c[0], c[2] = c[2], c[0]
- c[1], c[3] = c[3], c[1]
- c[2] += ((h - 1 - c[3]) * (c[2] - c[0])) // (c[3] - c[1])
- c[3] = h - 1
- else:
- if c[0] == c[2]:
- if c[1] < 0:
- c[1] = 0
- if c[3] < 0:
- c[3] = 0
- else:
- if c[3] < c[1]:
- c[0], c[2] = c[2], c[0]
- c[1], c[3] = c[3], c[1]
- c[0] += ((-c[1]) * (c[2] - c[0])) // (c[3] - c[1])
- c[1] = 0
- else:
- return True
-
- #### SETUP COMMANDS ####
-
- def set_power(self, on):
- self.pwr(on)
- sleep_ms(15)
-
- def set_orient(self, orient):
- self._fcmd2('<BBB', 0x14, (orient & 3) + 4)
- # update width and height variables
- self.iflush()
- self._send(b'\x02g0')
- self._waitfor(4, self.buf[5])
- self.w = self.buf[5][1]
- self.h = self.buf[5][2]
-
- def set_brightness(self, value):
- self._fcmd2('<BBB', 0x16, value)
-
- def set_i2c_addr(self, addr):
- # 0x0e set i2c addr
- if addr & 3:
- raise ValueError('must specify mod 4 aligned address')
- self._fcmd2('<BBW', 0x0e, 0x433249 | (addr << 24))
-
- def set_uart_baudrate(self, baudrate):
- try:
- baudrate = _uart_baud_table[baudrate]
- except KeyError:
- raise ValueError('invalid baudrate')
- self._fcmd2('<BBB', 0x18, baudrate)
-
- def set_startup_deco(self, value):
- self._fcmd2('<BBB', 0x19, value)
-
- def save_to_flash(self):
- self._send(b'\x02fn')
-
- #### PIXEL ACCESS ####
-
- def set_pixel(self, x, y, c):
- self._fcmd2b('<BBBBH', 0x41, x, y, c)
-
- def get_pixel(self, x, y):
- self._fcmd2('<BBBB', 0x61, x, y)
- t = 1000
- while t:
- self.i2c.readfrom_into(self.i2c_addr, self.buf1)
- if self.buf1[0] >= 2:
- self.i2c.readfrom_into(self.i2c_addr, self.buf[3])
- return self.buf[3][1] | self.buf[3][2] << 8
- t -= 1
- sleep_ms(1)
- raise OSError(uerrno.ETIMEDOUT)
-
- def get_line(self, x, y, buf):
- l = len(buf) // 2
- self._fcmd2b('<BBBBB', 0x10, l, x, y)
- l *= 2
- t = 1000
- while t:
- self.i2c.readfrom_into(self.i2c_addr, self.buf1)
- if self.buf1[0] >= l:
- self.i2c.readfrom_into(self.i2c_addr, buf)
- return
- t -= 1
- sleep_ms(1)
- raise OSError(uerrno.ETIMEDOUT)
-
- def screen_dump(self, buf, x=0, y=0, w=None, h=None):
- if w is None:
- w = self.w - x
- if h is None:
- h = self.h - y
- if w <= 127:
- line = bytearray(2 * w + 1)
- line2 = None
- else:
- # split line if more than 254 bytes needed
- buflen = (w + 1) // 2
- line = bytearray(2 * buflen + 1)
- line2 = memoryview(line)[:2 * (w - buflen) + 1]
- for i in range(min(len(buf) // (2 * w), h)):
- ix = i * w * 2
- self.get_line(x, y + i, line)
- buf[ix:ix + len(line) - 1] = memoryview(line)[1:]
- ix += len(line) - 1
- if line2:
- self.get_line(x + buflen, y + i, line2)
- buf[ix:ix + len(line2) - 1] = memoryview(line2)[1:]
- ix += len(line2) - 1
-
- def screen_load(self, buf):
- l = self.w * self.h * 2+2
- self._fcmd2b('<BBHBBB', 0x70, l, 16, self.w, self.h)
- n = 0
- ar = memoryview(buf)
- while n < len(buf):
- if len(buf) - n >= 0x200:
- self._send(ar[n:n + 0x200])
- n += 0x200
- else:
- self._send(ar[n:])
- while n < self.w * self.h * 2:
- self._send(b'\x00')
- n += 1
-
- #### TEXT COMMANDS ####
-
- def set_pos(self, x, y):
- self._fcmd2('<BBBB', 0x58, x, y)
-
- def set_text_color(self, fg, bg):
- self._fcmd2('<BBHH', 0x63, fg, bg)
-
- def set_font(self, font, scale=0, bold=0, trans=0, scroll=0):
- self._fcmd2('<BBBB', 0x46, (scroll << 7) | (trans << 6) | ((font & 3) << 4) | (bold & 0xf), scale & 0xff)
-
- def write(self, s):
- # TODO: eventually check for room in LCD input queue
- self._send(s)
-
- #### PRIMITIVE DRAWING COMMANDS ####
-
- def set_pen(self, line, fill):
- self._fcmd2('<BBHH', 0x50, line, fill)
-
- def erase(self):
- self._send(b'\x02\x45')
-
- def dot(self, x, y):
- if 0 <= x < self.w and 0 <= y < self.h:
- self._fcmd2('<BBBB', 0x4b, x, y)
-
- def rect(self, x, y, w, h, cmd=0x72):
- if x + w <= 0 or y + h <= 0 or x >= self.w or y >= self.h:
- return
- elif x < 0 or y < 0:
- left = top = True
- if x < 0:
- left = False
- w += x
- x = 0
- if y < 0:
- top = False
- h += y
- y = 0
- if cmd == 0x51 or cmd == 0x72:
- # draw interior
- self._fcmd2b('<BBBBBB', 0x51, x, y, min(w, 255), min(h, 255))
- if cmd == 0x57 or cmd == 0x72:
- # draw outline
- if left:
- self._fcmd2b('<BBBBBB', 0x57, x, y, 1, min(h, 255))
- if top:
- self._fcmd2b('<BBBBBB', 0x57, x, y, min(w, 255), 1)
- if x + w < self.w:
- self._fcmd2b('<BBBBBB', 0x57, x + w, y, 1, min(h, 255))
- if y + h < self.h:
- self._fcmd2b('<BBBBBB', 0x57, x, y + h, min(w, 255), 1)
- else:
- self._fcmd2b('<BBBBBB', cmd, x, y, min(w, 255), min(h, 255))
-
- def rect_outline(self, x, y, w, h):
- self.rect(x, y, w, h, 0x57)
-
- def rect_interior(self, x, y, w, h):
- self.rect(x, y, w, h, 0x51)
-
- def line(self, x1, y1, x2, y2):
- ar4 = self.array4
- ar4[0] = x1
- ar4[1] = y1
- ar4[2] = x2
- ar4[3] = y2
- if self.clip_line(ar4, self.w, self.h):
- self._fcmd2b('<BBBBBB', 0x4c, ar4[0], ar4[1], ar4[2], ar4[3])
-
- def dot_no_clip(self, x, y):
- self._fcmd2('<BBBB', 0x4b, x, y)
-
- def rect_no_clip(self, x, y, w, h):
- self._fcmd2b('<BBBBBB', 0x72, x, y, w, h)
-
- def rect_outline_no_clip(self, x, y, w, h):
- self._fcmd2b('<BBBBBB', 0x57, x, y, w, h)
-
- def rect_interior_no_clip(self, x, y, w, h):
- self._fcmd2b('<BBBBBB', 0x51, x, y, w, h)
-
- def line_no_clip(self, x1, y1, x2, y2):
- self._fcmd2b('<BBBBBB', 0x4c, x1, y1, x2, y2)
-
- def poly_dot(self, data):
- if len(data) & 1:
- raise ValueError('must specify even number of bytes')
- self._fcmd2('<BBB', 0x71, len(data) // 2)
- self._send(data)
-
- def poly_line(self, data):
- if len(data) & 1:
- raise ValueError('must specify even number of bytes')
- self._fcmd2('<BBB', 0x78, len(data) // 2)
- self._send(data)
-
- #### TOUCH COMMANDS ####
-
- def touch_config(self, calib=False, save=False, irq=None):
- self._fcmd2('<BBBB', 0x7a, (irq is not None) << 2 | save << 1 | calib, bool(irq) << 7)
-
- def is_touched(self):
- self._send(b'\x02T')
- b = self.buf[4]
- self._waitfor(3, b)
- return b[1] >> 7 != 0
-
- def get_touch(self):
- self._send(b'\x02T') # implicit LCD output flush
- b = self.buf[4]
- self._waitfor(3, b)
- return b[1] >> 7, b[2], b[3]
-
- #### ADVANCED COMMANDS ####
-
- def set_spi_win(self, x, y, w, h):
- pack_into('<BBBHHHHHHHH', self.buf19, 0, 2, 0x55, 10, x, y, x + w - 1, y + h - 1, 0, 0, 0, 0xffff)
- self._send(self.buf19)
-
- def fast_spi(self, flush=True):
- if flush:
- self.oflush()
- self._send(b'\x02\x12')
- return self.spi
-
- def show_framebuf(self, buf):
- self.fast_spi().write(buf)
-
- def set_scroll(self, on):
- self._fcmd2('<BBB', 0x15, on)
-
- def set_scroll_win(self, win, x=-1, y=0, w=0, h=0, vec=0, pat=0, fill=0x07e0, color=0):
- pack_into('<BBBHHHHHHHH', self.buf19, 0, 2, 0x55, win, x, y, w, h, vec, pat, fill, color)
- self._send(self.buf19)
-
- def set_scroll_win_param(self, win, param, value):
- self._fcmd2b('<BBBBH', 0x75, win, param, value)
-
- def set_scroll_buf(self, s):
- l = len(s)
- if l > 32:
- raise ValueError('length must be 32 or less')
- self._fcmd2('<BBB', 0x11, l)
- self._send(s)
-
- def jpeg_start(self, l):
- if l > 0xffff:
- raise ValueError('length must be 65535 or less')
- self.oflush()
- self._fcmd2('<BBH', 0x6a, l)
-
- def jpeg_data(self, buf):
- self._send(buf)
-
- def jpeg(self, buf):
- self.jpeg_start(len(buf))
- self.jpeg_data(buf)
-
- def feed_wdt(self):
- self._send(b'\x02\x17')
-
- def reset(self):
- self._send(b'\x02Y\xef\xbe\xad\xde')
- sleep_ms(15)
diff --git a/drivers/display/lcd160cr_test.py b/drivers/display/lcd160cr_test.py
deleted file mode 100644
index 8b7ef4555..000000000
--- a/drivers/display/lcd160cr_test.py
+++ /dev/null
@@ -1,171 +0,0 @@
-# Driver test for official MicroPython LCD160CR display
-# MIT license; Copyright (c) 2017 Damien P. George
-
-import time, math, framebuf, lcd160cr
-
-def get_lcd(lcd):
- if type(lcd) is str:
- lcd = lcd160cr.LCD160CR(lcd)
- return lcd
-
-def show_adc(lcd, adc):
- data = [adc.read_core_temp(), adc.read_core_vbat(), 3.3]
- try:
- data[2] = adc.read_vref()
- except:
- pass
- for i in range(3):
- lcd.set_text_color((825, 1625, 1600)[i], 0)
- if lcd.h == 160:
- lcd.set_font(2)
- lcd.set_pos(0, 100 + i * 16)
- else:
- lcd.set_font(2, trans=1)
- lcd.set_pos(0, lcd.h-60 + i * 16)
- lcd.write('%4s: ' % ('TEMP', 'VBAT', 'VREF')[i])
- if i > 0:
- s = '%6.3fV' % data[i]
- else:
- s = '%5.1f°C' % data[i]
- if lcd.h == 160:
- lcd.set_font(1, bold=0, scale=1)
- else:
- lcd.set_font(1, bold=0, scale=1, trans=1)
- lcd.set_pos(45, lcd.h-60 + i * 16)
- lcd.write(s)
-
-def test_features(lcd, orient=lcd160cr.PORTRAIT):
- # if we run on pyboard then use ADC and RTC features
- try:
- import pyb
- adc = pyb.ADCAll(12, 0xf0000)
- rtc = pyb.RTC()
- except:
- adc = None
- rtc = None
-
- # set orientation and clear screen
- lcd = get_lcd(lcd)
- lcd.set_orient(orient)
- lcd.set_pen(0, 0)
- lcd.erase()
-
- # create M-logo
- mlogo = framebuf.FrameBuffer(bytearray(17 * 17 * 2), 17, 17, framebuf.RGB565)
- mlogo.fill(0)
- mlogo.fill_rect(1, 1, 15, 15, 0xffffff)
- mlogo.vline(4, 4, 12, 0)
- mlogo.vline(8, 1, 12, 0)
- mlogo.vline(12, 4, 12, 0)
- mlogo.vline(14, 13, 2, 0)
-
- # create inline framebuf
- offx = 14
- offy = 19
- w = 100
- h = 75
- fbuf = framebuf.FrameBuffer(bytearray(w * h * 2), w, h, framebuf.RGB565)
- lcd.set_spi_win(offx, offy, w, h)
-
- # initialise loop parameters
- tx = ty = 0
- t0 = time.ticks_us()
-
- for i in range(300):
- # update position of cross-hair
- t, tx2, ty2 = lcd.get_touch()
- if t:
- tx2 -= offx
- ty2 -= offy
- if tx2 >= 0 and ty2 >= 0 and tx2 < w and ty2 < h:
- tx, ty = tx2, ty2
- else:
- tx = (tx + 1) % w
- ty = (ty + 1) % h
-
- # create and show the inline framebuf
- fbuf.fill(lcd.rgb(128 + int(64 * math.cos(0.1 * i)), 128, 192))
- fbuf.line(w // 2, h // 2,
- w // 2 + int(40 * math.cos(0.2 * i)),
- h // 2 + int(40 * math.sin(0.2 * i)),
- lcd.rgb(128, 255, 64))
- fbuf.hline(0, ty, w, lcd.rgb(64, 64, 64))
- fbuf.vline(tx, 0, h, lcd.rgb(64, 64, 64))
- fbuf.rect(tx - 3, ty - 3, 7, 7, lcd.rgb(64, 64, 64))
- for phase in (-0.2, 0, 0.2):
- x = w // 2 - 8 + int(50 * math.cos(0.05 * i + phase))
- y = h // 2 - 8 + int(32 * math.sin(0.05 * i + phase))
- fbuf.blit(mlogo, x, y)
- for j in range(-3, 3):
- fbuf.text('MicroPython',
- 5, h // 2 + 9 * j + int(20 * math.sin(0.1 * (i + j))),
- lcd.rgb(128 + 10 * j, 0, 128 - 10 * j))
- lcd.show_framebuf(fbuf)
-
- # show results from the ADC
- if adc:
- show_adc(lcd, adc)
-
- # show the time
- if rtc:
- lcd.set_pos(2, 0)
- lcd.set_font(1)
- t = rtc.datetime()
- lcd.write('%4d-%02d-%02d %2d:%02d:%02d.%01d' % (t[0], t[1], t[2], t[4], t[5], t[6], t[7] // 100000))
-
- # compute the frame rate
- t1 = time.ticks_us()
- dt = time.ticks_diff(t1, t0)
- t0 = t1
-
- # show the frame rate
- lcd.set_pos(2, 9)
- lcd.write('%.2f fps' % (1000000 / dt))
-
-def test_mandel(lcd, orient=lcd160cr.PORTRAIT):
- # set orientation and clear screen
- lcd = get_lcd(lcd)
- lcd.set_orient(orient)
- lcd.set_pen(0, 0xffff)
- lcd.erase()
-
- # function to compute Mandelbrot pixels
- def in_set(c):
- z = 0
- for i in range(32):
- z = z * z + c
- if abs(z) > 100:
- return i
- return 0
-
- # cache width and height of LCD
- w = lcd.w
- h = lcd.h
-
- # create the buffer for each line and set SPI parameters
- line = bytearray(w * 2)
- lcd.set_spi_win(0, 0, w, h)
- spi = lcd.fast_spi()
-
- # draw the Mandelbrot set line-by-line
- hh = ((h - 1) / 3.2)
- ww = ((w - 1) / 2.4)
- for v in range(h):
- for u in range(w):
- c = in_set((v / hh - 2.3) + (u / ww - 1.2) * 1j)
- if c < 16:
- rgb = c << 12 | c << 6
- else:
- rgb = 0xf800 | c << 6
- line[2 * u] = rgb
- line[2 * u + 1] = rgb >> 8
- spi.write(line)
-
-def test_all(lcd, orient=lcd160cr.PORTRAIT):
- lcd = get_lcd(lcd)
- test_features(lcd, orient)
- test_mandel(lcd, orient)
-
-print('To run all tests: test_all(<lcd>)')
-print('Individual tests are: test_features, test_mandel')
-print('<lcd> argument should be a connection, eg "X", or an LCD160CR object')
diff --git a/drivers/display/ssd1306.py b/drivers/display/ssd1306.py
deleted file mode 100644
index cd358d00e..000000000
--- a/drivers/display/ssd1306.py
+++ /dev/null
@@ -1,160 +0,0 @@
-# MicroPython SSD1306 OLED driver, I2C and SPI interfaces
-
-from micropython import const
-import framebuf
-
-
-# register definitions
-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 = self.height // 8
- self.buffer = bytearray(self.pages * self.width)
- fb = framebuf.FrameBuffer(self.buffer, self.width, self.height, framebuf.MONO_VLSB)
- self.framebuf = fb
- # Provide methods for accessing FrameBuffer graphics primitives. This is a
- # workround because inheritance from a native class is currently unsupported.
- # http://docs.micropython.org/en/latest/pyboard/library/framebuf.html
- self.fill = fb.fill
- self.pixel = fb.pixel
- self.hline = fb.hline
- self.vline = fb.vline
- self.line = fb.line
- self.rect = fb.rect
- self.fill_rect = fb.fill_rect
- self.text = fb.text
- self.scroll = fb.scroll
- self.blit = fb.blit
- self.init_display()
-
- def init_display(self):
- for cmd in (
- SET_DISP | 0x00, # off
- # address setting
- SET_MEM_ADDR, 0x00, # horizontal
- # resolution and layout
- SET_DISP_START_LINE | 0x00,
- SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0
- SET_MUX_RATIO, self.height - 1,
- SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0
- SET_DISP_OFFSET, 0x00,
- SET_COM_PIN_CFG, 0x02 if self.height == 32 else 0x12,
- # timing and driving scheme
- SET_DISP_CLK_DIV, 0x80,
- SET_PRECHARGE, 0x22 if self.external_vcc else 0xf1,
- SET_VCOM_DESEL, 0x30, # 0.83*Vcc
- # display
- SET_CONTRAST, 0xff, # maximum
- SET_ENTIRE_ON, # output follows RAM contents
- SET_NORM_INV, # not inverted
- # charge pump
- SET_CHARGE_PUMP, 0x10 if self.external_vcc else 0x14,
- SET_DISP | 0x01): # on
- self.write_cmd(cmd)
- self.fill(0)
- self.show()
-
- def poweroff(self):
- self.write_cmd(SET_DISP | 0x00)
-
- def poweron(self):
- self.write_cmd(SET_DISP | 0x01)
-
- def contrast(self, contrast):
- self.write_cmd(SET_CONTRAST)
- self.write_cmd(contrast)
-
- def invert(self, invert):
- self.write_cmd(SET_NORM_INV | (invert & 1))
-
- def show(self):
- x0 = 0
- x1 = self.width - 1
- if self.width == 64:
- # displays with width of 64 pixels are shifted by 32
- x0 += 32
- x1 += 32
- 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 << 1
- self.temp[1] = 0x40 # Co=0, D/C#=1
- self.i2c.start()
- self.i2c.write(self.temp)
- self.i2c.write(buf)
- self.i2c.stop()
-
-
-class SSD1306_SPI(SSD1306):
- def __init__(self, width, height, spi, dc, res, cs, external_vcc=False):
- self.rate = 10 * 1024 * 1024
- dc.init(dc.OUT, value=0)
- res.init(res.OUT, value=0)
- cs.init(cs.OUT, value=1)
- self.spi = spi
- self.dc = dc
- self.res = res
- self.cs = cs
- import time
- self.res(1)
- time.sleep_ms(1)
- self.res(0)
- time.sleep_ms(10)
- self.res(1)
- super().__init__(width, height, external_vcc)
-
- def write_cmd(self, cmd):
- self.spi.init(baudrate=self.rate, polarity=0, phase=0)
- self.cs(1)
- self.dc(0)
- self.cs(0)
- self.spi.write(bytearray([cmd]))
- self.cs(1)
-
- def write_data(self, buf):
- self.spi.init(baudrate=self.rate, polarity=0, phase=0)
- self.cs(1)
- self.dc(1)
- self.cs(0)
- self.spi.write(buf)
- self.cs(1)