Porównaj commity

...

7 Commity

Autor SHA1 Wiadomość Data
Peter Hinch 5eafeed7f7 Document user contributed drivers. 2023-09-02 11:21:21 +01:00
Peter Hinch 6894c4fbb6
Merge pull request #56 from EnricoRoss98/WeActStudio-EDP
Added driver for the WeAct Studio 2.9in EPD (SSD1680)
2023-09-02 10:08:15 +01:00
Peter Hinch 21a0d0dc40
Merge pull request #57 from EnricoRoss98/ST7567s
Added driver and setup-example for ST7567s displays
2023-09-02 10:04:03 +01:00
Enrico Rossini 6b37dbf1dc Optimized constants 2023-08-30 10:10:58 +02:00
Enrico Rossini 1670b5ee2c Moved driver from drivers/ssd1680 to drivers/epaper and removed useless demo 2023-08-30 10:06:53 +02:00
Enrico Rossini 5e50eb0880 Added driver and setup-example for the ST7567s LCD 128x64 display 2023-08-28 22:26:56 +02:00
Enrico Rossini c9fbe2a995 Added driver, demo and setup-example for the WeAct Studio 2.9in EPD display with the SSD1680 driver 2023-08-27 15:09:24 +02:00
8 zmienionych plików z 403 dodań i 27 usunięć

Wyświetl plik

@ -13,32 +13,34 @@ owing to their long update time.
Size is diagonal in inches. C/M/GS color/1-bit monochrome/greyscale.
Width and height are pixels.
| Size | Width | Height | Tech | Driver | Description | Notes |
|:------:|:-----:|:------:|:------|:--------------|:----------------------------|:------|
| 0.96C | 94 | 64 | OLED | [SSD1331][1d] | [Adafruit 684][1m] | |
| 1.12GS | 96 | 96 | OLED | [SSD1327][11d]| [Seeed 104030011][21m] | Obsolescent. |
| 1.27C | 128 | 96 | OLED | [SSD1351][2d] | [Adafruit 1673][2m] | |
| 1.5C | 128 | 128 | OLED | [SSD1351][2d] | [Adafruit 1431][3m] | |
| 1.44C | 128 | 128 | TFT | [ST7735R][4d] | [Adafruit 2088][5m] | |
| 1.5C | 160 | 128 | TFT | [ST7735R][4d] | [Adafruit 358][6m] | |
| 1.3C | 240 | 240 | TFT | [ST7789][5d] | [Adafruit 4313][7m] | |
| 1.5GS | 128 | 128 | OLED | [SSD1327][11d]| [Waveshare 13992][20m] | |
| 2.0C | 320 | 240 | TFT | [ST7789][5d] | [Waveshare Pico LCD 2][18m] | For Pi Pico. |
| 1.54C | 240 | 240 | TFT | [ST7789][5d] | [Adafruit 3787][8m] | |
| 1.14C | 240 | 135 | TFT | [ST7789][5d] | [T-Display][9m] | ESP32 with attached display. |
| 2.8C | 320 | 240 | TFT | [ST7789][5d] | [Waveshare pico 2.8][10m] | Display for Pi Pico. |
| 1.14C | 240 | 135 | TFT | [ST7789][5d] | [Waveshare pico 1.14][11m] | For Pi Pico. Buttons good for micro-gui. |
| 1.14C | 240 | 135 | TFT | [ST7789][5d] | [Pimoroni pico 1.14][23m] | For Pi Pico. Buttons good for micro-gui. |
| 3.2C | 320 | 240 | TFT | [ILI9341][6d] | [Adafruit 1743][12m] | Big display. eBay equivalents work here. |
| 3.5C | 480 | 320 | TFT | [ILI9486][12d]| [Waveshare Rpi 3.5 LCD][22m]| Pi HAT. Many pixels. Needs plenty of RAM. |
| 3.5C | 480 | 320 | TFT | [ILI9486][12d]| [Adafruit 3.5 LCD][24m] | 3.5" HX8357D display, notes as above. |
| 3.5C | 480 | 320 | TFT | [ILI9486][12d]| [Waveshere RPI 3.5 LCD][25m]| 3.5" ILI9488 display, notes as above. |
| 2.9M | 296 | 128 | eInk | [UC8151D][7d] | [Adafruit 4262][13m] | Flexible ePaper display. |
| 2.9M | 296 | 128 | eInk | [UC8151D][7d] | [Adafruit 4777][15m] | FeatherWing ePaper display. |
| 4.2M | 400 | 300 | eInk | [WS][10d] | [Waveshare pico 4.2][19m] | Pico, Pico W plug in. Other hosts via cable. |
| 2.7M | 274 | 176 | eInk | [HAT][8d] | [Waveshare HAT][14m] | HAT designed for Raspberry Pi, repurposed. |
| 2.7M | 400 | 240 | Sharp | [Sharp][9d] | [Adafruit 4694][16m] | Micropower monochrome display. |
| 1.3M | 168 | 144 | Sharp | [Sharp][9d] | [Adafruit 3502][17m] | Ditto. |
| Size | Width | Height | Tech | Driver | Description | Notes |
|:------:|:-----:|:------:|:------|:---------------|:-----------------------------|:---------------------------------------------|
| 0.96C | 94 | 64 | OLED | [SSD1331][1d] | [Adafruit 684][1m] | |
| 1.12GS | 96 | 96 | OLED | [SSD1327][11d] | [Seeed 104030011][21m] | Obsolescent. |
| 1.27C | 128 | 96 | OLED | [SSD1351][2d] | [Adafruit 1673][2m] | |
| 1.5C | 128 | 128 | OLED | [SSD1351][2d] | [Adafruit 1431][3m] | |
| 1.4M | 128 | 64 | LCD | [SSD7567s][16d]| [ST7567s][27m] | Similar to SSD1306 |
| 1.44C | 128 | 128 | TFT | [ST7735R][4d] | [Adafruit 2088][5m] | |
| 1.5C | 160 | 128 | TFT | [ST7735R][4d] | [Adafruit 358][6m] | |
| 1.3C | 240 | 240 | TFT | [ST7789][5d] | [Adafruit 4313][7m] | |
| 1.5GS | 128 | 128 | OLED | [SSD1327][11d] | [Waveshare 13992][20m] | |
| 2.0C | 320 | 240 | TFT | [ST7789][5d] | [Waveshare Pico LCD 2][18m] | For Pi Pico. |
| 1.54C | 240 | 240 | TFT | [ST7789][5d] | [Adafruit 3787][8m] | |
| 1.14C | 240 | 135 | TFT | [ST7789][5d] | [T-Display][9m] | ESP32 with attached display. |
| 2.8C | 320 | 240 | TFT | [ST7789][5d] | [Waveshare pico 2.8][10m] | Display for Pi Pico. |
| 1.14C | 240 | 135 | TFT | [ST7789][5d] | [Waveshare pico 1.14][11m] | For Pi Pico. Buttons good for micro-gui. |
| 1.14C | 240 | 135 | TFT | [ST7789][5d] | [Pimoroni pico 1.14][23m] | For Pi Pico. Buttons good for micro-gui. |
| 3.2C | 320 | 240 | TFT | [ILI9341][6d] | [Adafruit 1743][12m] | Big display. eBay equivalents work here. |
| 3.5C | 480 | 320 | TFT | [ILI9486][12d] | [Waveshare Rpi 3.5 LCD][22m] | Pi HAT. Many pixels. Needs plenty of RAM. |
| 3.5C | 480 | 320 | TFT | [ILI9486][12d] | [Adafruit 3.5 LCD][24m] | 3.5" HX8357D display, notes as above. |
| 3.5C | 480 | 320 | TFT | [ILI9486][12d] | [Waveshere RPI 3.5 LCD][25m] | 3.5" ILI9488 display, notes as above. |
| 2.9M | 296 | 128 | eInk | [UC8151D][7d] | [Adafruit 4262][13m] | Flexible ePaper display. |
| 2.9M | 296 | 128 | eInk | [UC8151D][7d] | [Adafruit 4777][15m] | FeatherWing ePaper display. |
| 2.9M | 296 | 128 | eInk | [SSD1680][15d] | [WeAct Studio ePaper][26m] | WeAct Studio ePaper display. |
| 4.2M | 400 | 300 | eInk | [WS][10d] | [Waveshare pico 4.2][19m] | Pico, Pico W plug in. Other hosts via cable. |
| 2.7M | 274 | 176 | eInk | [HAT][8d] | [Waveshare HAT][14m] | HAT designed for Raspberry Pi, repurposed. |
| 2.7M | 400 | 240 | Sharp | [Sharp][9d] | [Adafruit 4694][16m] | Micropower monochrome display. |
| 1.3M | 168 | 144 | Sharp | [Sharp][9d] | [Adafruit 3502][17m] | Ditto. |
## Displays using compatible drivers
@ -58,6 +60,13 @@ AKA [KeyStudio](https://wiki.keyestudio.com/Ks0056_keyestudio_1.3%22_128x64_OLED
Nokia 5110 (PCD8544) displays. [This driver](https://github.com/mcauser/micropython-pcd8544.git)
is compatible.
## User contributed drivers
The following drivers were contibuted by users. I am unable to support these as
I don't possess the relevant hardware.
SSD7567s contributed by EnricoRoss98 [PR](https://github.com/peterhinch/micropython-nano-gui/pull/57)
SSD1680.py contributed by EnricoRoss98 [PR](https://github.com/peterhinch/micropython-nano-gui/pull/56)
## Adafruit displays
See [these notes](./ADAFRUIT.md) for wiring details, pin names and hardware
@ -105,6 +114,8 @@ simple. See [this doc](./DRIVERS.md#7-writing-device-drivers) for details.
[12d]: https://github.com/peterhinch/micropython-nano-gui/blob/master/DRIVERS.md#34-driver-for-ili9486
[13d]: https://github.com/peterhinch/micropython-nano-gui/blob/master/drivers/sh1106/sh1106.py
[14d]: https://github.com/peterhinch/micropython-nano-gui/blob/master/drivers/ssd1306/ssd1306.py
[15d]: https://github.com/peterhinch/micropython-nano-gui/blob/master/DRIVERS.md#54-weact-studio-ssd1680-eink-displays
[16d]: https://github.com/peterhinch/micropython-nano-gui/blob/master/drivers/st7567s/st7567s.py
[1m]: https://www.adafruit.com/product/684
[2m]: https://www.adafruit.com/product/1673
@ -131,4 +142,5 @@ simple. See [this doc](./DRIVERS.md#7-writing-device-drivers) for details.
[23m]: https://shop.pimoroni.com/products/pico-display-pack?variant=32368664215635
[24m]: https://www.adafruit.com/product/2050
[25m]: https://www.waveshare.com/wiki/Pico-ResTouch-LCD-3.5
[26m]: https://aliexpress.com/item/1005004644515880.html
[27m]: https://www.buydisplay.com/1-4-inch-graphic-128x64-lcd-module-serial-spi-st7567s-black-on-white

Wyświetl plik

@ -1374,6 +1374,20 @@ Color values of 0 (white) to 3 (black) can explicitly be specified.
###### [Contents](./DRIVERS.md#contents)
## 5.4 WeAct Studio SSD1680 eInk Displays
The driver supports the WeAct Studio SSD1680 2.9 inch 296*128 pixel
[display](https://github.com/WeActStudio/WeActStudio.EpaperModule) that uses the
[SSD1680 driver](https://github.com/WeActStudio/WeActStudio.EpaperModule/blob/master/Doc/SSD1680.pdf).
This display lacks many features when compared to the ones from Waveshare,
two important examples are fast refresh and partial refresh. The big pro however is the price,
it costs half the money of the Waveshare 2.9in alternative.
The driver is cross platform and supports landscape or portrait mode. To keep
the buffer size down (to 4736 bytes) there is no greyscale support. It should
be noted that WeAct Studio product page suggests to not update the display more frequently than every 180s.
# 6. EPD Asynchronous support
The following applies to nano-gui. Under micro-gui the update mechanism is

Wyświetl plik

@ -0,0 +1,203 @@
# epd29_ssd1680.py
# Nanogui driver for WeAct Studio 2.9" Black and White ePaper display.
# This driver can be used with the 2.13" EPD from WeAct Studio or with
# other displays with the same driver however, on my tests changing the resolution
# may rise exception, but I manage to successfully use this driver with the smaller
# display without changing the resolution.
# [Display](https://github.com/WeActStudio/WeActStudio.EpaperModule)
# EPD is subclassed from framebuf.FrameBuffer for use with Writer class and nanogui.
# Released under the MIT license see LICENSE
# Based on the following sources:
# https://github.com/peterhinch/micropython-nano-gui/blob/master/drivers/epaper/epd29.py
# https://github.com/hfwang132/ssd1680-micropython-drivers
# Driver contributed by Enrico Rossini @EnricoRoss98
# https://github.com/peterhinch/micropython-nano-gui/pull/56
# You can run a demo for this driver by executing the demo script "epd29_sync.py"
import framebuf
import uasyncio as asyncio
from micropython import const
from time import sleep_ms, sleep_us, ticks_ms, ticks_us, ticks_diff
from gui.drivers.boolpalette import BoolPalette
from machine import lightsleep, Pin
class TimeoutError(Exception):
def __init__(self, msg):
super().__init__(msg)
class EPD(framebuf.FrameBuffer):
# A monochrome approach should be used for coding this. The rgb method ensures
# nothing breaks if users specify colors.
@staticmethod
def rgb(r, g, b):
return int((r > 127) or (g > 127) or (b > 127))
# Discard asyn: autodetect
def __init__(self, spi, cs, dc, rst_pin, busy, landscape=True):
self._spi = spi
self._cs = cs # Pins
self._dc = dc
self._rst = Pin(rst_pin, Pin.OUT, value=1)
self._rst_pin = rst_pin
self._busy = busy # Pin High if Busy
self._lsc = landscape
# ._as_busy is set immediately on start of task. Cleared
# when busy pin is physically 0.
self._as_busy = False
self.updated = asyncio.Event()
self.complete = asyncio.Event()
# Public bound variables required by nanogui.
# Dimensions in pixels as seen by nanogui (landscape mode).
self.width = 296 if landscape else 128
self.height = 128 if landscape else 296
# Other public bound variable.
# Special mode enables demos written for generic displays to run.
self.demo_mode = False
self._buffer = bytearray(self.height * self.width // 8)
self._mvb = memoryview(self._buffer)
mode = framebuf.MONO_VLSB if landscape else framebuf.MONO_HLSB
self.palette = BoolPalette(mode)
super().__init__(self._buffer, self.width, self.height, mode)
self.init()
def _command(self, command, data=None):
self._dc(0)
self._spi.write(command)
self._dc(1)
if data is not None:
self._data(data)
def _data(self, data, buf1=bytearray(1)):
for b in data:
buf1[0] = b
self._spi.write(buf1)
def hw_reset(self):
self._rst(1)
sleep_ms(200)
self._rst(0)
sleep_ms(200)
self._rst(1)
self.wait_until_ready()
# print("hardware reset successful")
def init(self):
# Hardware reset
self.hw_reset()
self._dc(1)
self._cs(0)
# Initialisation
cmd = self._command
# Software Reset
# print("software resetting...")
# cmd(b'\x12')
# self.wait_until_ready()
# print("software reset successful")
# deriver output control
cmd(b'\x01', b'\x27\x01\x01')
# data entry mode
cmd(b'\x11', b'\x01')
# set ram-x addr start/end pos
cmd(b'\x44', b'\x00\x0F')
# set ram-y addr start/end pos
cmd(b'\x45', b'\x27\x01\x00\x00')
# border waveform
cmd(b'\x3c', b'\x05')
# display update control
cmd(b'\x21', b'\x00\x80')
# set ram-x addr cnt to 0
cmd(b'\x4e', b'\x00')
# set ram-y addr cnt to 0x127
cmd(b'\x4F', b'\x27\x01')
# set to use internal temperature sensor
cmd(b'\x18', b'\x80')
'''
# read from internal temperature sensor
self._dc(0)
self._spi.write(b'\x1B')
print(self._spi.read(2))
self._dc(1)
print(self._spi.read(2))
'''
self.wait_until_ready()
# print('Init Done.')
# For use in synchronous code: blocking wait on ready state.
def wait_until_ready(self):
sleep_ms(50)
while not self.ready():
sleep_ms(100)
# Return immediate status. Pin state: 1 == busy.
def ready(self):
return not (self._as_busy or (self._busy() == 1))
# draw the current frame memory.
def show(self, buf1=bytearray(1),
fast_refresh=False, # USELESS for this driver, doesn't work well at all
deepsleep_after_refresh=False,
lightsleep_while_waiting_for_refresh=False):
if not self.ready():
# Hardware reset to exit deep sleep mode
self.hw_reset()
mvb = self._mvb
cmd = self._command
dat = self._data
cmd(b'\x24')
if self._lsc: # Landscape mode
wid = self.width
tbc = self.height // 8 # Vertical bytes per column
iidx = wid * (tbc - 1) # Initial index
idx = iidx # Index into framebuf
vbc = 0 # Current vertical byte count
hpc = 0 # Horizontal pixel count
for _ in range(len(mvb)):
buf1[0] = ~mvb[idx]
dat(buf1)
idx -= wid
vbc += 1
vbc %= tbc
if not vbc:
hpc += 1
idx = iidx + hpc
else:
for b in mvb:
buf1[0] = ~b
dat(buf1)
if fast_refresh:
cmd(b'\x22', b'\xFF')
else:
cmd(b'\x22', b'\xF7')
sleep_us(20)
cmd(b'\x20') # DISPLAY_REFRESH
if lightsleep_while_waiting_for_refresh:
# set Pin hold=True is needed before entering lightsleep and after you must revert it back to hold=False
# without this, entering lightsleep results in a low state on the reset pin, and this resets the driver
self._rst = Pin(self._rst_pin, Pin.OUT, value=1, hold=True)
lightsleep(3000) # can be used to lowering consumption on ESP32
self._rst = Pin(self._rst_pin, Pin.OUT, value=1, hold=False)
self.wait_until_ready()
if deepsleep_after_refresh:
cmd(b'\x10', b'\x01')
else:
cmd(b'\x10', b'\x00')

Wyświetl plik

@ -4,6 +4,7 @@
["drivers/epaper/epaper2in7_fb.py", "github:peterhinch/micropython-nano-gui/drivers/epaper/epaper2in7_fb.py"],
["drivers/epaper/pico_epaper_42_gs.py", "github:peterhinch/micropython-nano-gui/drivers/epaper/pico_epaper_42_gs.py"],
["drivers/epaper/pico_epaper_42.py", "github:peterhinch/micropython-nano-gui/drivers/epaper/pico_epaper_42.py"],
["drivers/epaper/epd29_ssd1680.py", "github:peterhinch/micropython-nano-gui/drivers/epaper/epd29_ssd1680.py"],
["drivers/boolpalette.py", "github:peterhinch/micropython-nano-gui/drivers/boolpalette.py"]
],
"version": "0.1"

Wyświetl plik

@ -0,0 +1,7 @@
{
"urls": [
["drivers/st7567s/st7567s.py", "github:peterhinch/micropython-nano-gui/drivers/st7567s/st7567s.pyy"],
["drivers/boolpalette.py", "github:peterhinch/micropython-nano-gui/drivers/boolpalette.py"]
],
"version": "0.1"
}

Wyświetl plik

@ -0,0 +1,104 @@
# st7567s.py
# Released under the MIT License (MIT). See LICENSE.
# Driver contributed by Enrico Rossini @EnricoRoss98
# https://github.com/peterhinch/micropython-nano-gui/pull/57
from micropython import const
from gui.drivers.boolpalette import BoolPalette
from time import sleep_ms
import framebuf
# LCD Commands definition
_CMD_DISPLAY_ON = const(0xAF)
_CMD_DISPLAY_OFF = const(0xAE)
_CMD_SET_START_LINE = const(0x40)
_CMD_SET_PAGE = const(0xB0)
_CMD_COLUMN_UPPER = const(0x10)
_CMD_COLUMN_LOWER = const(0x00)
_CMD_SET_ADC_NORMAL = const(0xA0)
_CMD_SET_ADC_REVERSE = const(0xA1)
_CMD_SET_COL_NORMAL = const(0xC0)
_CMD_SET_COL_REVERSE = const(0xC8)
_CMD_SET_DISPLAY_NORMAL = const(0xA6)
_CMD_SET_DISPLAY_REVERSE = const(0xA7)
_CMD_SET_ALLPX_ON = const(0xA5)
_CMD_SET_ALLPX_NORMAL = const(0xA4)
_CMD_SET_BIAS_9 = const(0xA2)
_CMD_SET_BIAS_7 = const(0xA3)
_CMD_DISPLAY_RESET = const(0xE2)
_CMD_NOP = const(0xE3)
_CMD_TEST = const(0xF0) # Exit this mode with _CMD_NOP
_CMD_SET_POWER = const(0x28)
_CMD_SET_RESISTOR_RATIO = const(0x20)
_CMD_SET_VOLUME = const(0x81)
# Display parameters
_DISPLAY_W = const(128)
_DISPLAY_H = const(64)
_DISPLAY_CONTRAST = const(0x1B)
_DISPLAY_RESISTOR_RATIO = const(5)
_DISPLAY_POWER_MODE = 7
class ST7567(framebuf.FrameBuffer):
@staticmethod
def rgb(r, g, b):
return min((r + g + b) >> 7, 3) # Greyscale in range 0 <= gs <= 3
def __init__(self, width, height, i2c, addr=0x3F, external_vcc=False):
self.i2c = i2c
self.addr = addr
self.temp = bytearray(2)
self.write_list = [b"\x40", None] # Co=0, D/C#=1
self.width = width
self.height = height
self.external_vcc = external_vcc
self.pages = self.height // 8
self.buffer = bytearray(self.pages * self.width)
mode = framebuf.MONO_VLSB
self.palette = BoolPalette(mode) # Ensure color compatibility
super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB)
self.display_init()
def display_init(self):
self.write_cmd(_CMD_DISPLAY_RESET)
sleep_ms(1)
for cmd in (
_CMD_DISPLAY_OFF, # Display off
_CMD_SET_BIAS_9, # Display drive voltage 1/9 bias
_CMD_SET_ADC_NORMAL, # Normal SEG
_CMD_SET_COL_REVERSE, # Commmon mode reverse direction
_CMD_SET_RESISTOR_RATIO + _DISPLAY_RESISTOR_RATIO, # V5 R ratio
_CMD_SET_VOLUME, # Contrast
_DISPLAY_CONTRAST, # Contrast value
_CMD_SET_POWER + _DISPLAY_POWER_MODE):
self.write_cmd(cmd)
self.show()
self.write_cmd(_CMD_DISPLAY_ON)
def set_contrast(self, value):
if (0x1 <= value <= 0x3f):
for cmd in (_CMD_SET_VOLUME, value):
self.write_cmd(cmd)
def show(self):
for i in range(8):
for cmd in (
_CMD_SET_START_LINE,
_CMD_SET_PAGE + i,
_CMD_COLUMN_UPPER,
_CMD_COLUMN_LOWER):
self.write_cmd(cmd)
self.write_data(self.buffer[i * 128:(i + 1) * 128])
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.write_list[1] = buf
self.i2c.writevto(self.addr, self.write_list)

Wyświetl plik

@ -0,0 +1,22 @@
# WIRING
# 15 BUSY
# 4 DC
# 2 Rst
# 5 CS
# 23 SDA
# 18 SCL
from machine import Pin, SPI
import gc
# *** Choose your color display driver here ***
from drivers.epaper.epd29_ssd1680 import EPD as SSD
dc = Pin(4, Pin.OUT, value=0)
rst_pin = 2
cs = Pin(5, Pin.OUT, value=1)
busy = Pin(15, Pin.IN)
spi = SPI(1, baudrate=10000000, sck=Pin(18), mosi=Pin(23))
gc.collect() # Precaution before instantiating framebuf
ssd = SSD(spi, cs, dc, rst_pin, busy, landscape=True)

Wyświetl plik

@ -0,0 +1,13 @@
from machine import Pin, SoftI2C
import gc
# *** Choose your color display driver here ***
from drivers.st7567s.st7567s import ST7567 as SSD
# ESP32 Pin assignment
i2c = SoftI2C(scl=Pin(33), sda=Pin(32), freq=100000)
lcd_width = 128
lcd_height = 64
gc.collect() # Precaution before instantiating framebuf
ssd = SSD(lcd_width, lcd_height, i2c)