kopia lustrzana https://github.com/peterhinch/micropython-nano-gui
Update SSD1331 drivers, fix color bug in 16 bit version. Doc improvements.
rodzic
c9b8990de8
commit
8c30e2fbec
11
ADAFRUIT.md
11
ADAFRUIT.md
|
@ -61,10 +61,11 @@ i2c = machine.I2C(scl=pscl, sda=psda)
|
|||
If the SD card is to be used, the official `scdard.py` driver should be
|
||||
employed. This may be found
|
||||
[here](https://github.com/micropython/micropython/tree/master/drivers/sdcard).
|
||||
Note that `sdtest.py` initialises the SPI bus before accessing the SD card.
|
||||
This is necessary because the display drivers use a high baudrate unsupported
|
||||
by SD cards. Ensure applications do this before the first SD card access and
|
||||
before subsequent ones if the display has been refreshed.
|
||||
It is necessary to initialise the SPI bus before accessing the SD card. This is
|
||||
because the display drivers use a high baudrate unsupported by SD cards. Ensure
|
||||
applications do this before the first SD card access and before subsequent ones
|
||||
if the display has been refreshed. See
|
||||
[sdtest.py](https://github.com/micropython/micropython/blob/master/drivers/sdcard/sdtest.py).
|
||||
|
||||
# Notes on OLED displays
|
||||
|
||||
|
@ -97,4 +98,4 @@ figures. I have not seen figures for the Adafruit displays.
|
|||
Options are to blank the display when not required, or to design screens where
|
||||
the elements are occasionally moved slightly to preserve individual pixels.
|
||||
|
||||
###### [Main README](../README.md)
|
||||
###### [Main README](./README.md)
|
||||
|
|
56
DRIVERS.md
56
DRIVERS.md
|
@ -42,7 +42,7 @@ from drivers.ssd1351.ssd1351 import SSD1351 as SSD # Choose device driver
|
|||
pdc = machine.Pin('Y1', machine.Pin.OUT_PP, value=0)
|
||||
pcs = machine.Pin('Y2', machine.Pin.OUT_PP, value=1)
|
||||
prst = machine.Pin('Y3', machine.Pin.OUT_PP, value=1)
|
||||
spi = machine.SPI(2)
|
||||
spi = machine.SPI(2, baudrate=10_000_000) # baudrate depends on display chip
|
||||
gc.collect() # Precaution before instantiating framebuf
|
||||
ssd = SSD(spi, pcs, pdc, prst, 96) # Create a display instance
|
||||
```
|
||||
|
@ -109,6 +109,10 @@ For further information see the GUI README
|
|||
|
||||
This driver was tested on Adafruit 1.5 and 1.27 inch displays.
|
||||
|
||||
The `color_setup.py` file should initialise the SPI bus with a baudrate of
|
||||
20_000_000. Args `polarity`, `phase`, `bits`, `firstbit` are defaults. Hard or
|
||||
soft SPI may be used but hard may be faster.
|
||||
|
||||
#### SSD1351 Constructor args:
|
||||
* `spi` An SPI bus instance.
|
||||
* `pincs` An initialised output pin. Initial value should be 1.
|
||||
|
@ -143,7 +147,9 @@ s[x + 1] 2nd byte sent g4 g3 g2 r7 r6 r5 r4 r3
|
|||
|
||||
# 3. Drivers for SSD1331
|
||||
|
||||
See [Adafruit 0.96" OLED display](https://www.adafruit.com/product/684).
|
||||
See [Adafruit 0.96" OLED display](https://www.adafruit.com/product/684). Most
|
||||
of the demos assume a larger screen and will fail. The `color96.py` demo is
|
||||
written for this display.
|
||||
|
||||
There are two versions. Both are cross-platform.
|
||||
* `ssd1331.py` Uses 8 bit rrrgggbb color.
|
||||
|
@ -151,10 +157,15 @@ There are two versions. Both are cross-platform.
|
|||
|
||||
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.
|
||||
well because text and controls are normally drawn with a limited range of
|
||||
colors, most of which are saturated.
|
||||
|
||||
The 16 bit version provides greatly improved results when rendering images.
|
||||
|
||||
The `color_setup.py` file should initialise the SPI bus with a baudrate of
|
||||
6_666_000. Args `polarity`, `phase`, `bits`, `firstbit` are defaults. Hard or
|
||||
soft SPI may be used but hard may be faster.
|
||||
|
||||
#### SSD1331 Constructor args:
|
||||
* `spi` An SPI bus instance.
|
||||
* `pincs` An initialised output pin. Initial value should be 1.
|
||||
|
@ -162,9 +173,17 @@ The 16 bit version provides greatly improved results when rendering images.
|
|||
* `pinrs` An initialised output pin. Initial value should be 1.
|
||||
* `height=64` Display dimensions in pixels.
|
||||
* `width=96`
|
||||
|
||||
This driver initialises the SPI clock rate and polarity as required by the
|
||||
device. The device can support clock rates of upto 6.66MHz.
|
||||
* `init_spi=False` This optional arg enables flexible options in configuring
|
||||
the SPI bus. The default assumes exclusive access to the bus with
|
||||
`color_setup.py` initialising it. Those settings will be left in place. If a
|
||||
callback function is passed, it will be called prior to each SPI bus write:
|
||||
this is for shared bus applications. The callback will receive a single arg
|
||||
being the SPI bus instance. In normal use it will be a one-liner or lambda
|
||||
initialising the bus. A minimal example is this function:
|
||||
```python
|
||||
def spi_init(spi):
|
||||
spi.init(baudrate=6_666_000) # Data sheet: max is 150ns
|
||||
```
|
||||
|
||||
# 4. Drivers for ST7735R
|
||||
|
||||
|
@ -182,6 +201,10 @@ the supported Adafruit displays differ in their initialisation settings.
|
|||
If your Chinese display doesn't work with my drivers you are on your own: I
|
||||
can't support hardware I don't possess.
|
||||
|
||||
The `color_setup.py` file should initialise the SPI bus with a baudrate of
|
||||
12_000_000. Args `polarity`, `phase`, `bits`, `firstbit` are defaults. Hard or
|
||||
soft SPI may be used but hard may be faster.
|
||||
|
||||
#### ST7735R Constructor args:
|
||||
* `spi` An initialised SPI bus instance. The device can support clock rates of
|
||||
upto 15MHz.
|
||||
|
@ -209,6 +232,10 @@ def spi_init(spi):
|
|||
Adafruit make several displays using this chip, for example
|
||||
[this 3.2 inch unit](https://www.adafruit.com/product/1743).
|
||||
|
||||
The `color_setup.py` file should initialise the SPI bus with a baudrate of
|
||||
10_000_000. Args `polarity`, `phase`, `bits`, `firstbit` are defaults. Hard or
|
||||
soft SPI may be used but hard may be faster. See note on overclocking below.
|
||||
|
||||
#### ILI9341 Constructor args:
|
||||
* `spi` An initialised SPI bus instance. The device can support clock rates of
|
||||
upto 10MHz.
|
||||
|
@ -255,10 +282,27 @@ An application using this should call `refresh(ssd, True)` once at the start,
|
|||
then launch the `do_refresh` method. After that, no calls to `refresh` should
|
||||
be made. See `gui/demos/scale_ili.py`.
|
||||
|
||||
Another option to reduce blocking is overclocking the SPI bus.
|
||||
|
||||
#### Overclocking SPI
|
||||
|
||||
The ILI9341 datasheet section 19.3.4 specifies a minimum clock cycle time of
|
||||
100ns for write cycles. It seems that every man and his dog overclocks this,
|
||||
even the normally conservative Adafruit
|
||||
[use 24MHz](https://learn.adafruit.com/adafruit-2-8-and-3-2-color-tft-touchscreen-breakout-v2/python-usage)
|
||||
and [rdagger](https://github.com/rdagger/micropython-ili9341/blob/master/demo_fonts.py)
|
||||
uses 40MHz. I have successfully run my display at 40MHz. My engineering
|
||||
training makes me baulk at exceeding datasheet limits but the choice is yours.
|
||||
|
||||
###### [Contents](./DRIVERS.md#contents)
|
||||
|
||||
# 6. Drivers for sharp displays
|
||||
|
||||
These displays have characteristics which mean that they are best suited to
|
||||
micropower applications. Inevitably this means that deployment is more involved
|
||||
than the other supported units. This doc provides some background information
|
||||
on their use.
|
||||
|
||||
These monochrome SPI displays exist in three variants from Adafruit.
|
||||
1. [2.7 inch 400x240 pixels](https://www.adafruit.com/product/4694)
|
||||
2. [1.3 inch 144x168](https://www.adafruit.com/product/3502)
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
# color_setup.py Customise for your hardware config
|
||||
|
||||
# Released under the MIT License (MIT). See LICENSE.
|
||||
# Copyright (c) 2020 Peter Hinch
|
||||
|
||||
# As written, supports:
|
||||
# Adafruit 1.5" 128*128 OLED display: https://www.adafruit.com/product/1431
|
||||
# Adafruit 1.27" 128*96 display https://www.adafruit.com/product/1673
|
||||
# Edit the driver import for other displays.
|
||||
|
||||
# Demo of initialisation procedure designed to minimise risk of memory fail
|
||||
# when instantiating the frame buffer. The aim is to do this as early as
|
||||
# possible before importing other modules.
|
||||
|
||||
# SSD1331 drivers are cross-platform.
|
||||
# WIRING (Adafruit pin nos and names with Pyboard pins).
|
||||
# Pyb SSD
|
||||
# 3v3 Vin (10)
|
||||
# Gnd Gnd (11)
|
||||
# X1 DC (3 DC)
|
||||
# X2 CS (5 OC OLEDCS)
|
||||
# X3 Rst (4 R RESET)
|
||||
# X6 CLK (2 CL SCK)
|
||||
# X8 DATA (1 SI MOSI)
|
||||
|
||||
import machine
|
||||
import gc
|
||||
|
||||
from drivers.ssd1331.ssd1331 import SSD1331 as SSD
|
||||
|
||||
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, baudrate=6_666_000)
|
||||
gc.collect() # Precaution before instantiating framebuf
|
||||
ssd = SSD(spi, pcs, pdc, prst) # Create a display instance
|
|
@ -3,25 +3,8 @@
|
|||
|
||||
# The MIT License (MIT)
|
||||
|
||||
# Copyright (c) 2018 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.
|
||||
# Copyright (c) Peter Hinch 2018-2020
|
||||
# Released under the MIT license see LICENSE
|
||||
|
||||
# Show command
|
||||
# 0x15, 0, 0x5f, 0x75, 0, 0x3f Col 0-95 row 0-63
|
||||
|
@ -52,8 +35,9 @@ import gc
|
|||
import sys
|
||||
# https://github.com/peterhinch/micropython-nano-gui/issues/2
|
||||
# The ESP32 does not work reliably in SPI mode 1,1. Waveforms look correct.
|
||||
# Keep 0,0 on STM as testing was done in that mode.
|
||||
_bs = 0 if sys.platform == 'esp32' else 1 # SPI bus state
|
||||
# Mode 0, 0 works on ESP and STM
|
||||
|
||||
# Data sheet SPI spec: 150ns min clock period 6.66MHz
|
||||
|
||||
class SSD1331(framebuf.FrameBuffer):
|
||||
# Convert r, g, b in range 0-255 to an 8 bit colour value
|
||||
|
@ -62,18 +46,17 @@ class SSD1331(framebuf.FrameBuffer):
|
|||
def rgb(r, g, b):
|
||||
return (r & 0xe0) | ((g >> 3) & 0x1c) | (b >> 6)
|
||||
|
||||
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
|
||||
def __init__(self, spi, pincs, pindc, pinrs, height=64, width=96, init_spi=False):
|
||||
self._spi = spi
|
||||
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.GS8 # Use 8bit greyscale for 8 bit color.
|
||||
self._spi_init = init_spi
|
||||
mode = framebuf.GS8 # Use 8bit greyscale for 8 bit color.
|
||||
gc.collect()
|
||||
self.buffer = bytearray(self.height * self.width)
|
||||
super().__init__(self.buffer, self.width, self.height, self.mode)
|
||||
super().__init__(self.buffer, self.width, self.height, mode)
|
||||
pinrs(0) # Pulse the reset line
|
||||
utime.sleep_ms(1)
|
||||
pinrs(1)
|
||||
|
@ -85,13 +68,14 @@ class SSD1331(framebuf.FrameBuffer):
|
|||
self.show()
|
||||
|
||||
def _write(self, buf, dc):
|
||||
self.spi.init(baudrate=self.rate, polarity=_bs, phase=_bs)
|
||||
self.pincs(1)
|
||||
self.pindc(dc)
|
||||
self.pincs(0)
|
||||
self.spi.write(buf)
|
||||
self.pincs(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
|
||||
if self._spi_init: # A callback was passed
|
||||
self._spi_init(spi) # Bus may be shared
|
||||
self._write(_cmd, 0)
|
||||
self._write(self.buffer, 1)
|
||||
|
|
|
@ -1,27 +1,8 @@
|
|||
# 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.
|
||||
# Copyright (c) Peter Hinch 2019-2020
|
||||
# Released under the MIT license see LICENSE
|
||||
|
||||
# Show command
|
||||
# 0x15, 0, 0x5f, 0x75, 0, 0x3f Col 0-95 row 0-63
|
||||
|
@ -49,35 +30,37 @@
|
|||
import framebuf
|
||||
import utime
|
||||
import gc
|
||||
import sys
|
||||
|
||||
# https://github.com/peterhinch/micropython-nano-gui/issues/2
|
||||
# The ESP32 does not work reliably in SPI mode 1,1. Waveforms look correct.
|
||||
# Keep 0,0 on STM as testing was done in that mode.
|
||||
_bs = 0 if sys.platform == 'esp32' else 1 # SPI bus state
|
||||
# Mode 0, 0 works on ESP and STM
|
||||
|
||||
# Data sheet SPI spec: 150ns min clock period 6.66MHz
|
||||
class SSD1331(framebuf.FrameBuffer):
|
||||
# Convert r, g, b in range 0-255 to a 16 bit colour value RGB565
|
||||
# acceptable to hardware: rrrrrggggggbbbbb
|
||||
# LS byte of 16 bit result is shifted out 1st
|
||||
@staticmethod
|
||||
def rgb(r, g, b):
|
||||
return ((r & 0xf8) << 5) | ((g & 0x1c) << 11) | (b & 0xf8) | ((g & 0xe0) >> 5)
|
||||
return ((b & 0xf8) << 5) | ((g & 0x1c) << 11) | (r & 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
|
||||
def __init__(self, spi, pincs, pindc, pinrs, height=64, width=96, init_spi=False):
|
||||
self._spi = spi
|
||||
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
|
||||
self._spi_init = init_spi
|
||||
mode = framebuf.RGB565
|
||||
gc.collect()
|
||||
self.buffer = bytearray(self.height * self.width * 2)
|
||||
super().__init__(self.buffer, self.width, self.height, self.mode)
|
||||
super().__init__(self.buffer, self.width, self.height, mode)
|
||||
pinrs(0) # Pulse the reset line
|
||||
utime.sleep_ms(1)
|
||||
pinrs(1)
|
||||
utime.sleep_ms(1)
|
||||
if self._spi_init: # A callback was passed
|
||||
self._spi_init(spi) # Bus may be shared
|
||||
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)
|
||||
|
@ -85,13 +68,14 @@ class SSD1331(framebuf.FrameBuffer):
|
|||
self.show()
|
||||
|
||||
def _write(self, buf, dc):
|
||||
self.spi.init(baudrate=self.rate, polarity=_bs, phase=_bs)
|
||||
self.pincs(1)
|
||||
self.pindc(dc)
|
||||
self.pincs(0)
|
||||
self.spi.write(buf)
|
||||
self.pincs(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
|
||||
if self._spi_init: # A callback was passed
|
||||
self._spi_init(spi) # Bus may be shared
|
||||
self._write(_cmd, 0)
|
||||
self._write(self.buffer, 1)
|
||||
|
|
Ładowanie…
Reference in New Issue