diff options
Diffstat (limited to 'drivers/display')
| -rw-r--r-- | drivers/display/lcd160cr.py | 474 | ||||
| -rw-r--r-- | drivers/display/lcd160cr_test.py | 171 | ||||
| -rw-r--r-- | drivers/display/ssd1306.py | 160 |
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) |
