From 630810de0dbc77e0416f1746240da1efaf68078b Mon Sep 17 00:00:00 2001 From: Peter Hinch Date: Tue, 25 Jun 2019 14:16:05 +0100 Subject: [PATCH] Add SSD1331 RGB565 driver. --- drivers/ssd1331/README.md | 11 ++++ drivers/ssd1331/ssd1331_16bit.py | 92 +++++++++++++++++++++++++++++++ drivers/ssd1331/test_colors.py | 31 +++++++++++ drivers/ssd1351/ssd1351_16bit.py | 2 +- drivers/ssd1351/test_colors_96.py | 27 +++++++++ 5 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 drivers/ssd1331/README.md create mode 100644 drivers/ssd1331/ssd1331_16bit.py create mode 100644 drivers/ssd1331/test_colors.py create mode 100644 drivers/ssd1351/test_colors_96.py diff --git a/drivers/ssd1331/README.md b/drivers/ssd1331/README.md new file mode 100644 index 0000000..2d6c6df --- /dev/null +++ b/drivers/ssd1331/README.md @@ -0,0 +1,11 @@ +# Drivers for SSD1331 (Adafruit 0.96" OLED display) + +There are two versions. Both are designed to be cross-platform. + * `ssd1331.py` Uses 8 bit rrrgggbb color. + * `ssd1331_16bit.py` Uses 16 bit RGB565 color. + +The `ssd1331_16bit` version requires 12KiB of RAM for the frame buffer, while +the standard version needs only 6KiB. For the GUI the standard version works +well because text and controls are normally drawn with saturated colors. + +The 16 bit version provides greatly improved results when rendering images. diff --git a/drivers/ssd1331/ssd1331_16bit.py b/drivers/ssd1331/ssd1331_16bit.py new file mode 100644 index 0000000..ad378b1 --- /dev/null +++ b/drivers/ssd1331/ssd1331_16bit.py @@ -0,0 +1,92 @@ +# SSD1331.py MicroPython driver for Adafruit 0.96" OLED display +# https://www.adafruit.com/product/684 + +# The MIT License (MIT) + +# Copyright (c) 2019 Peter Hinch + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +# Show command +# 0x15, 0, 0x5f, 0x75, 0, 0x3f Col 0-95 row 0-63 + +# Initialisation command +# 0xae display off (sleep mode) +# 0xa0, 0x72 16 bit RGB, horizontal RAM increment +# 0xa1, 0x00 Startline row 0 +# 0xa2, 0x00 Vertical offset 0 +# 0xa4 Normal display +# 0xa8, 0x3f Set multiplex ratio +# 0xad, 0x8e Ext supply +# 0xb0, 0x0b Disable power save mode +# 0xb1, 0x31 Phase period +# 0xb3, 0xf0 Oscillator frequency +# 0x8a, 0x64, 0x8b, 0x78, 0x8c, 0x64, # Precharge +# 0xbb, 0x3a Precharge voltge +# 0xbe, 0x3e COM deselect level +# 0x87, 0x06 master current attenuation factor +# 0x81, 0x91 contrast for all color "A" segment +# 0x82, 0x50 contrast for all color "B" segment +# 0x83, 0x7d contrast for all color "C" segment +# 0xaf Display on + +import framebuf +import utime +import gc + +class SSD1331(framebuf.FrameBuffer): + # Convert r, g, b in range 0-255 to a 16 bit colour value RGB565 + # acceptable to hardware: rrrrrggggggbbbbb + @staticmethod + def rgb(r, g, b): + return ((r & 0xf8) << 5) | ((g & 0x1c) << 11) | (b & 0xf8) | ((g & 0xe0) >> 5) + + def __init__(self, spi, pincs, pindc, pinrs, height=64, width=96): + self.spi = spi + self.rate = 6660000 # Data sheet: 150ns min clock period + self.pincs = pincs + self.pindc = pindc # 1 = data 0 = cmd + self.height = height # Required by Writer class + self.width = width + # Save color mode for use by writer_gui (blit) + self.mode = framebuf.RGB565 + gc.collect() + self.buffer = bytearray(self.height * self.width * 2) + super().__init__(self.buffer, self.width, self.height, self.mode) + pinrs(0) # Pulse the reset line + utime.sleep_ms(1) + pinrs(1) + utime.sleep_ms(1) + self._write(b'\xae\xa0\x72\xa1\x00\xa2\x00\xa4\xa8\x3f\xad\x8e\xb0'\ + b'\x0b\xb1\x31\xb3\xf0\x8a\x64\x8b\x78\x8c\x64\xbb\x3a\xbe\x3e\x87'\ + b'\x06\x81\x91\x82\x50\x83\x7d\xaf', 0) + gc.collect() + self.show() + + def _write(self, buf, dc): + self.spi.init(baudrate=self.rate, polarity=1, phase=1) + self.pincs(1) + self.pindc(dc) + self.pincs(0) + self.spi.write(buf) + self.pincs(1) + + def show(self, _cmd=b'\x15\x00\x5f\x75\x00\x3f'): # Pre-allocate + self._write(_cmd, 0) + self._write(self.buffer, 1) diff --git a/drivers/ssd1331/test_colors.py b/drivers/ssd1331/test_colors.py new file mode 100644 index 0000000..f816be0 --- /dev/null +++ b/drivers/ssd1331/test_colors.py @@ -0,0 +1,31 @@ +# test_colors.py Test color rendition on SSD1331 (Adafruit 0.96" OLED). +# Author Peter Hinch +# Released under the MIT licence. + +import machine +# Can test either driver +# from ssd1331 import SSD1331 as SSD +from ssd1331_16bit import SSD1331 as SSD + +# Initialise hardware +def setup(): + pdc = machine.Pin('X1', machine.Pin.OUT_PP, value=0) + pcs = machine.Pin('X2', machine.Pin.OUT_PP, value=1) + prst = machine.Pin('X3', machine.Pin.OUT_PP, value=1) + spi = machine.SPI(1) + ssd = SSD(spi, pcs, pdc, prst) # Create a display instance + return ssd + +ssd = setup() +ssd.fill(0) +# Operate in landscape mode +x = 0 +for y in range(96): + ssd.line(y, x, y, x+20, ssd.rgb(round(255*y/96), 0, 0)) +x += 20 +for y in range(96): + ssd.line(y, x, y, x+20, ssd.rgb(0, round(255*y/96), 0)) +x += 20 +for y in range(96): + ssd.line(y, x, y, x+20, ssd.rgb(0, 0, round(255*y/96))) +ssd.show() diff --git a/drivers/ssd1351/ssd1351_16bit.py b/drivers/ssd1351/ssd1351_16bit.py index 4cec9bc..0b7df2d 100644 --- a/drivers/ssd1351/ssd1351_16bit.py +++ b/drivers/ssd1351/ssd1351_16bit.py @@ -9,7 +9,7 @@ # The MIT License (MIT) -# Copyright (c) 2018 Peter Hinch +# Copyright (c) 2019 Peter Hinch # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal diff --git a/drivers/ssd1351/test_colors_96.py b/drivers/ssd1351/test_colors_96.py new file mode 100644 index 0000000..483edac --- /dev/null +++ b/drivers/ssd1351/test_colors_96.py @@ -0,0 +1,27 @@ +# test_colors_96.py +# Check color mapping. Runs on 96 row display (change height for 128 row) + +import machine +from ssd1351_16bit import SSD1351 as SSD + +# Initialise hardware +def setup(): + pdc = machine.Pin('X1', machine.Pin.OUT_PP, value=0) + pcs = machine.Pin('X2', machine.Pin.OUT_PP, value=1) + prst = machine.Pin('X3', machine.Pin.OUT_PP, value=1) + spi = machine.SPI(1) + ssd = SSD(spi, pcs, pdc, prst, height=96) # Create a display instance + return ssd + +ssd = setup() +ssd.fill(0) +x = 0 +for y in range(128): + ssd.line(y, x, y, x+20, ssd.rgb(round(255*y/128), 0, 0)) +x += 20 +for y in range(128): + ssd.line(y, x, y, x+20, ssd.rgb(0, round(255*y/128), 0)) +x += 20 +for y in range(128): + ssd.line(y, x, y, x+20, ssd.rgb(0, 0, round(255*y/128))) +ssd.show()