From a3210353d42d4b0aea28dee1f967d7734ad708e2 Mon Sep 17 00:00:00 2001 From: Alex J Lennon Date: Sun, 5 Aug 2018 15:28:52 +0100 Subject: [PATCH] ssd1306oled: Add display of scrolling DoES logo Signed-off-by: Alex J Lennon --- LoraOledESP32/ssd1306oled.ipynb | 271 +++++++++++++++++++++++++++++--- 1 file changed, 248 insertions(+), 23 deletions(-) diff --git a/LoraOledESP32/ssd1306oled.ipynb b/LoraOledESP32/ssd1306oled.ipynb index ab2346f..a8b187f 100644 --- a/LoraOledESP32/ssd1306oled.ipynb +++ b/LoraOledESP32/ssd1306oled.ipynb @@ -2,14 +2,14 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": 83, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "\u001b[34mConnecting to Serial /dev/ttyUSB2 baud=115200 \u001b[0m\n", + "\u001b[34mConnecting to --port=/dev/ttyUSB0 --baud=115200 \u001b[0m\n", "\u001b[34mReady.\n", "\u001b[0m" ] @@ -21,27 +21,191 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Sent 168 lines (5477 bytes) to ssd1306.py.\n" + "Sent 147 lines (4584 bytes) to ssd1306.py.\n" ] } ], "source": [ - "%sendtofile --source ssd1306.py\n" + "%sendtofile ssd1306.py\n", + "\n", + "# MicroPython SSD1306 OLED driver, I2C and SPI interfaces\n", + "\n", + "from micropython import const\n", + "import framebuf\n", + "\n", + "\n", + "# register definitions\n", + "SET_CONTRAST = const(0x81)\n", + "SET_ENTIRE_ON = const(0xa4)\n", + "SET_NORM_INV = const(0xa6)\n", + "SET_DISP = const(0xae)\n", + "SET_MEM_ADDR = const(0x20)\n", + "SET_COL_ADDR = const(0x21)\n", + "SET_PAGE_ADDR = const(0x22)\n", + "SET_DISP_START_LINE = const(0x40)\n", + "SET_SEG_REMAP = const(0xa0)\n", + "SET_MUX_RATIO = const(0xa8)\n", + "SET_COM_OUT_DIR = const(0xc0)\n", + "SET_DISP_OFFSET = const(0xd3)\n", + "SET_COM_PIN_CFG = const(0xda)\n", + "SET_DISP_CLK_DIV = const(0xd5)\n", + "SET_PRECHARGE = const(0xd9)\n", + "SET_VCOM_DESEL = const(0xdb)\n", + "SET_CHARGE_PUMP = const(0x8d)\n", + "\n", + "# Subclassing FrameBuffer provides support for graphics primitives\n", + "# http://docs.micropython.org/en/latest/pyboard/library/framebuf.html\n", + "class SSD1306(framebuf.FrameBuffer):\n", + " def __init__(self, width, height, external_vcc):\n", + " self.width = width\n", + " self.height = height\n", + " self.external_vcc = external_vcc\n", + " self.pages = self.height // 8\n", + " self.buffer = bytearray(self.pages * self.width)\n", + " super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB)\n", + " self.init_display()\n", + "\n", + " def init_display(self):\n", + " for cmd in (\n", + " SET_DISP | 0x00, # off\n", + " # address setting\n", + " SET_MEM_ADDR, 0x00, # horizontal\n", + " # resolution and layout\n", + " SET_DISP_START_LINE | 0x00,\n", + " SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0\n", + " SET_MUX_RATIO, self.height - 1,\n", + " SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0\n", + " SET_DISP_OFFSET, 0x00,\n", + " SET_COM_PIN_CFG, 0x02 if self.height == 32 else 0x12,\n", + " # timing and driving scheme\n", + " SET_DISP_CLK_DIV, 0x80,\n", + " SET_PRECHARGE, 0x22 if self.external_vcc else 0xf1,\n", + " SET_VCOM_DESEL, 0x30, # 0.83*Vcc\n", + " # display\n", + " SET_CONTRAST, 0xff, # maximum\n", + " SET_ENTIRE_ON, # output follows RAM contents\n", + " SET_NORM_INV, # not inverted\n", + " # charge pump\n", + " SET_CHARGE_PUMP, 0x10 if self.external_vcc else 0x14,\n", + " SET_DISP | 0x01): # on\n", + " self.write_cmd(cmd)\n", + " self.fill(0)\n", + " self.show()\n", + "\n", + " def poweroff(self):\n", + " self.write_cmd(SET_DISP | 0x00)\n", + "\n", + " def poweron(self):\n", + " self.write_cmd(SET_DISP | 0x01)\n", + "\n", + " def contrast(self, contrast):\n", + " self.write_cmd(SET_CONTRAST)\n", + " self.write_cmd(contrast)\n", + "\n", + " def invert(self, invert):\n", + " self.write_cmd(SET_NORM_INV | (invert & 1))\n", + "\n", + " def show(self):\n", + " x0 = 0\n", + " x1 = self.width - 1\n", + " if self.width == 64:\n", + " # displays with width of 64 pixels are shifted by 32\n", + " x0 += 32\n", + " x1 += 32\n", + " self.write_cmd(SET_COL_ADDR)\n", + " self.write_cmd(x0)\n", + " self.write_cmd(x1)\n", + " self.write_cmd(SET_PAGE_ADDR)\n", + " self.write_cmd(0)\n", + " self.write_cmd(self.pages - 1)\n", + " self.write_data(self.buffer)\n", + "\n", + "\n", + "class SSD1306_I2C(SSD1306):\n", + " def __init__(self, width, height, i2c, addr=0x3c, external_vcc=False):\n", + " self.i2c = i2c\n", + " self.addr = addr\n", + " self.temp = bytearray(2)\n", + " super().__init__(width, height, external_vcc)\n", + "\n", + " def write_cmd(self, cmd):\n", + " self.temp[0] = 0x80 # Co=1, D/C#=0\n", + " self.temp[1] = cmd\n", + " self.i2c.writeto(self.addr, self.temp)\n", + "\n", + " def write_data(self, buf):\n", + " self.temp[0] = self.addr << 1\n", + " self.temp[1] = 0x40 # Co=0, D/C#=1\n", + " self.i2c.start()\n", + " self.i2c.write(self.temp)\n", + " self.i2c.write(buf)\n", + " self.i2c.stop()\n", + "\n", + "\n", + "class SSD1306_SPI(SSD1306):\n", + " def __init__(self, width, height, spi, dc, res, cs, external_vcc=False):\n", + " self.rate = 10 * 1024 * 1024\n", + " dc.init(dc.OUT, value=0)\n", + " res.init(res.OUT, value=0)\n", + " cs.init(cs.OUT, value=1)\n", + " self.spi = spi\n", + " self.dc = dc\n", + " self.res = res\n", + " self.cs = cs\n", + " import time\n", + " self.res(1)\n", + " time.sleep_ms(1)\n", + " self.res(0)\n", + " time.sleep_ms(10)\n", + " self.res(1)\n", + " super().__init__(width, height, external_vcc)\n", + "\n", + " def write_cmd(self, cmd):\n", + " self.spi.init(baudrate=self.rate, polarity=0, phase=0)\n", + " self.cs(1)\n", + " self.dc(0)\n", + " self.cs(0)\n", + " self.spi.write(bytearray([cmd]))\n", + " self.cs(1)\n", + "\n", + " def write_data(self, buf):\n", + " self.spi.init(baudrate=self.rate, polarity=0, phase=0)\n", + " self.cs(1)\n", + " self.dc(1)\n", + " self.cs(0)\n", + " self.spi.write(buf)\n", + " self.cs(1)" ] }, { "cell_type": "code", - "execution_count": 3, - "metadata": { - "collapsed": true - }, + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['boot.py', 'hmac.py', 'hotpie.py', 'ssd1306.py']\r\n" + ] + } + ], + "source": [ + "import os\n", + "print(os.listdir())" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, "outputs": [], "source": [ "#https://forum.micropython.org/viewtopic.php?f=18&p=23080\n", @@ -53,6 +217,7 @@ "scl = Pin(15, Pin.OUT, Pin.PULL_UP)\n", "sda = Pin(4, Pin.OUT, Pin.PULL_UP)\n", "i2c = I2C(scl=scl, sda=sda, freq=450000)\n", + "\n", "o = ssd1306.SSD1306_I2C(128, 64, i2c, addr=0x3c)\n", "\n", "o.fill(0)\n", @@ -63,14 +228,16 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 80, "metadata": {}, "outputs": [ { - "name": "stdout", + "name": "stderr", "output_type": "stream", "text": [ - "[60]\r\n" + "Traceback (most recent call last):\n", + " File \"\", line 1, in \n", + "NameError: name 'i2c' is not defined\n" ] } ], @@ -80,12 +247,22 @@ }, { "cell_type": "code", - "execution_count": 27, - "metadata": { - "collapsed": true - }, - "outputs": [], + "execution_count": 81, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Traceback (most recent call last):\n", + " File \"\", line 3, in \n", + "NameError: name 'o' is not defined\n" + ] + } + ], "source": [ + "import framebuf\n", + "\n", "o.fill(0)\n", "for i in range(128):\n", " o.framebuf.fill_rect(1, 3, i, 34, 1)\n", @@ -114,12 +291,60 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] + "execution_count": 84, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + ".......\u001b[34m\n", + "\n", + "*** Sending Ctrl-C\n", + "\n", + "\u001b[0m" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Traceback (most recent call last):\n", + " File \"\", line 28, in \n", + "KeyboardInterrupt: \n" + ] + } + ], + "source": [ + "# Show the DoES logo. Scrolls across the screen\n", + "\n", + "import ssd1306\n", + "import framebuf\n", + "from machine import I2C, Pin\n", + "rst = Pin(16, Pin.OUT)\n", + "rst.value(1)\n", + "scl = Pin(15, Pin.OUT, Pin.PULL_UP)\n", + "sda = Pin(4, Pin.OUT, Pin.PULL_UP)\n", + "i2c = I2C(scl=scl, sda=sda, freq=450000)\n", + "display = ssd1306.SSD1306_I2C(128, 64, i2c, addr=0x3c)\n", + "#o = ssd1306.SSD1306_I2C(128, 64, i2c, addr=0x3c)\n", + "\n", + "buffer = bytearray(\n", + " b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xe7\\xe0\\x30\\x0f\\xff\\xf0\\x07\\x00\\xe0\\x30\\x03\\xff\\xf0\\x06\\x18\\xe0\\x31\\xe3\\xe1\\xf3\\xfe\\x3c\\xe0\\x31\\xf1\\xc0\\x73\\xfe\\x3f\\xe0\\x31\\xf1\\x8c\\x73\\xff\\x07\\xe0\\x31\\xf1\\x9e\\x30\\x07\\x80\\xe0\\x31\\xf1\\x1e\\x30\\x0f\\xf0\\x60\\x31\\xf1\\x1e\\x33\\xff\\xfc\\x60\\x31\\xf3\\x9e\\x33\\xfe\\x7e\\x60\\x31\\xc3\\x8e\\x73\\xfe\\x3c\\x60\\x30\\x07\\xc0\\x70\\x07\\x00\\xe0\\x30\\x1f\\xe1\\xf0\\x07\\x81\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x3f\\xff\\xff\\xff\\xff\\xff\\xe0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x40\\x00\\x00\\x00\\x00\\x60\\x30\\x00\\x00\\x00\\x00\\x00\\x60\\x30\\x48\\x8c\\x15\\x86\\x0c\\x60\\x30\\x49\\xb6\\xe6\\xcd\\x9b\\x60\\x30\\x49\\xb2\\xc4\\x58\\xb3\\x60\\x30\\x4d\\x3e\\xc4\\x58\\xb3\\x60\\x30\\x47\\x30\\xc4\\x49\\xb3\\x60\\x3f\\x46\\x1e\\xc7\\xcf\\x1e\\x60\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n", + ")\n", + "# FRAMEBUF_MHLSB = 3\n", + "fb = framebuf.FrameBuffer(buffer, 56, 64,3)\n", + "\n", + "while True:\n", + " for x in range(0,128-56):\n", + " display.fill(0)\n", + " display.blit(fb, x, 0)\n", + " display.show()\n", + " for x in range(0,128-56):\n", + " display.fill(0)\n", + " display.blit(fb, (128-56-x), 0)\n", + " display.show()\n" + ] } ], "metadata": {