Documentation improvements.

ili9341
Peter Hinch 2020-11-29 10:26:11 +00:00
rodzic d00fc77382
commit 5dbcc65828
7 zmienionych plików z 103 dodań i 142 usunięć

112
README.md
Wyświetl plik

@ -1,10 +1,10 @@
A lightweight and minimal MicroPython GUI library for display drivers based on A lightweight and minimal MicroPython GUI library for display drivers based on
the `framebuf` class. Various display technologies are supported, primarily the `FrameBuffer` class. Various display technologies are supported, including
small color OLED's. The GUI is cross-platform. small color and monochrome OLED's and color TFT's. The GUI is cross-platform.
These images don't do justice to the OLED displays which are visually These images, most from OLED displays, are poor. OLEDs are visually impressive
impressive with bright colors and extreme contrast. For some reason they are displays with bright colors, wide viewing angle and extreme contrast. For some
quite hard to photograph. reason I find them hard to photograph well.
![Image](images/clock.png) The aclock.py demo. ![Image](images/clock.png) The aclock.py demo.
![Image](images/fonts.png) Label objects in two fonts. ![Image](images/fonts.png) Label objects in two fonts.
@ -64,11 +64,15 @@ wiring details, pin names and hardware issues.
# 1. Introduction # 1. Introduction
This library provides a limited set of GUI objects (widgets) for displays whose This library provides a limited set of GUI objects (widgets) for displays whose
display driver is subclassed from the `framebuf` class. The GUI is display-only display driver is subclassed from the `FrameBuffer` class. Such drivers can be
and lacks provision for user input. This is because no `framebuf` based display tiny as the graphics primitives are supplied by the `FrameBuffer` class.
drivers exist for screens with a touch overlay. This is probably because touch
overlays require too many pixels and are best suited to displays with internal The GUI is display-only and lacks provision for user input. Displays with touch
frame buffers. overlays are physically large, with correspondingly high pixel counts. Such
displays would require large frame buffers. These would consume RAM and be slow
to copy to the display. A `FrameBuffer` based driver is ill-suited to large
displays. Drivers should use graphics primitives hosted on the display
controller chip.
The GUI is cross-platform. By default it is configured for a Pyboard (1.x or D). The GUI is cross-platform. By default it is configured for a Pyboard (1.x or D).
This doc explains how to configure for other platforms by adapting a single This doc explains how to configure for other platforms by adapting a single
@ -85,9 +89,10 @@ following displays. These have internal buffers:
## 1.1 Update ## 1.1 Update
17 Nov 2020 29 Nov 2020 Add ST7735R TFT drivers.
Add `Textbox` widget. `Scale` constructor arg `border` replaced by `bdcolor` as
per other widgets. 17 Nov 2020 Add `Textbox` widget. `Scale` constructor arg `border` replaced by
`bdcolor` as per other widgets.
5 Nov 2020 5 Nov 2020
This library has been refactored as a Python package. The aim is to reduce RAM This library has been refactored as a Python package. The aim is to reduce RAM
@ -115,15 +120,18 @@ Compatible and tested display drivers include:
* A driver for Sharp ultra low power consumption monochrome displays such as * A driver for Sharp ultra low power consumption monochrome displays such as
[2.7 inch 400x240 pixels](https://www.adafruit.com/product/4694) [2.7 inch 400x240 pixels](https://www.adafruit.com/product/4694)
is [here](./drivers/sharp/README.md). is [here](./drivers/sharp/README.md).
* Drivers for Adafruit ST7735R based TFT's:
[1.8 inch](https://www.adafruit.com/product/358) and
[1.44 inch](https://www.adafruit.com/product/2088).
Widgets are intended for the display of data from physical devices such as Widgets are intended for the display of data from physical devices such as
sensors. They are drawn using graphics primitives rather than icons to minimise sensors. They are drawn using graphics primitives rather than icons to minimise
RAM usage. It also enables them to be effciently rendered at arbitrary scale on RAM usage. It also enables them to be effciently rendered at arbitrary scale on
devices with restricted processing power. The approach also enables widgets to by hosts with restricted processing power. The approach also enables widgets to
maximise information in ways that are difficult with icons, in particular using maximise information in ways that are difficult with icons, in particular using
dynamic color changes in conjunction with moving elements. dynamic color changes in conjunction with moving elements.
Owing to RAM requirements and limitations on communication speed, `framebuf` Owing to RAM requirements and limitations on communication speed, `FrameBuffer`
based display drivers are intended for physically small displays with limited based display drivers are intended for physically small displays with limited
numbers of pixels. The widgets are designed for displays as small as 0.96 numbers of pixels. The widgets are designed for displays as small as 0.96
inches: this involves some compromises. inches: this involves some compromises.
@ -133,7 +141,7 @@ time depends on the size of the frame buffer and the interface speed, but the
latency may be too high for applications such as games. For example the time to latency may be too high for applications such as games. For example the time to
update a 128x128x8 color ssd1351 display on a Pyboard 1.0 is 41ms. update a 128x128x8 color ssd1351 display on a Pyboard 1.0 is 41ms.
Drivers based on `framebuf` must allocate contiguous RAM for the buffer. To Drivers based on `FrameBuffer` must allocate contiguous RAM for the buffer. To
avoid 'out of memory' errors it is best to instantiate the display before avoid 'out of memory' errors it is best to instantiate the display before
importing other modules. The demos illustrate this. importing other modules. The demos illustrate this.
@ -178,14 +186,15 @@ for SSD1351 displays only the following are actually required:
### 2.1.1 Core files ### 2.1.1 Core files
The root directory contains setup files for monochrome and color displays. The root directory contains two example setup files, for monochrome and color
These are templates for adaptation: only one file will normally need to be displays respectively. Other examples may be found in the `color_setup`
copied to the target. Color files should be named `color_setup.py` on the directory. These are templates for adaptation: only one file is copied to the
target, whereas the monochrome `ssd1306_setup.py` retains its own name. target. On the target a color files should be named `color_setup.py`. The
monochrome `ssd1306_setup.py` retains its own name.
The chosen template will need to be edited to match the display in use, the The chosen template will need to be edited to match the display in use, the
MicroPython target and the electrical connections between display and target. MicroPython target and the electrical connections between display and target.
Electrical connections are detailed in the source. Electrical connections are detailed in the driver source.
* `color_setup.py` Setup for color displays. As written supports an SSD1351 * `color_setup.py` Setup for color displays. As written supports an SSD1351
display connected to a Pyboard. display connected to a Pyboard.
* `ssd1306_setup.py` Setup file for monochrome displays using the official * `ssd1306_setup.py` Setup file for monochrome displays using the official
@ -213,8 +222,7 @@ The `gui/demos` directory contains test/demo scripts.
monochrome 128*64 OLED display. monochrome 128*64 OLED display.
* `color96.py` Tests/demos for the Adafruit 0.96 inch color OLED. * `color96.py` Tests/demos for the Adafruit 0.96 inch color OLED.
Demos for Adafruit 1.27 inch and 1.5 inch color OLEDs. These will run on either Demos for larger displays.
display so long as `color_setup.py` has the correct `height` value.
* `color15.py` Demonstrates a variety of widgets. Cross platform. * `color15.py` Demonstrates a variety of widgets. Cross platform.
* `aclock.py` Analog clock demo. Cross platform. * `aclock.py` Analog clock demo. Cross platform.
* `alevel.py` Spirit level using Pyboard accelerometer. * `alevel.py` Spirit level using Pyboard accelerometer.
@ -243,8 +251,8 @@ Python font files are in the `gui/fonts` directory. The easiest way to conserve
RAM is to freeze them which is highly recommended. In doing so the directory RAM is to freeze them which is highly recommended. In doing so the directory
structure must be maintained. Python fonts may be created using structure must be maintained. Python fonts may be created using
[font_to_py.py](https://github.com/peterhinch/micropython-font-to-py.git). The [font_to_py.py](https://github.com/peterhinch/micropython-font-to-py.git). The
`-x` option for horizontal mapping must be specified, along with -f for fixed `-x` option for horizontal mapping must be specified. If fixed pitch rendering
pitch rendering. Supplied examples are: is required `-f` is also required. Supplied examples are:
* `arial10.py` Variable pitch Arial in various sizes. * `arial10.py` Variable pitch Arial in various sizes.
* `arial35.py` * `arial35.py`
@ -267,6 +275,8 @@ copied to the hardware root as `color_setup.py`.
somewhat experimental. somewhat experimental.
* `st7735r_setup.py` Assumes a Pyboard with an * `st7735r_setup.py` Assumes a Pyboard with an
[Adafruit 1.8 inch TFT display](https://www.adafruit.com/product/358). [Adafruit 1.8 inch TFT display](https://www.adafruit.com/product/358).
* `st7735r144_setup.py` For a Pyboard with an
[Adafruit 1.44 inch TFT display](https://www.adafruit.com/product/2088).
## 2.2 Dependencies ## 2.2 Dependencies
@ -280,7 +290,6 @@ Optional feature:
* An STM32 implementation of * An STM32 implementation of
[this optimisation](https://github.com/peterhinch/micropython-font-to-py/blob/master/writer/WRITER.md#224-a-performance-boost). [this optimisation](https://github.com/peterhinch/micropython-font-to-py/blob/master/writer/WRITER.md#224-a-performance-boost).
### 2.2.1 Monochrome use ### 2.2.1 Monochrome use
A copy of the official driver for OLED displays using the SSD1306 chip is A copy of the official driver for OLED displays using the SSD1306 chip is
@ -294,7 +303,6 @@ in this repo but may be found here:
The Sharp display is supported in `drivers/sharp`. See The Sharp display is supported in `drivers/sharp`. See
[README](/drivers/sharp/README.md) and demos. [README](/drivers/sharp/README.md) and demos.
### 2.2.2 Color use ### 2.2.2 Color use
Drivers for Adafruit 0.96", 1.27" and 1.5" OLEDS are included in the source Drivers for Adafruit 0.96", 1.27" and 1.5" OLEDS are included in the source
@ -348,8 +356,8 @@ the border is at `[row-2, col-2]`.
When a widget is drawn or updated (typically with its `value` method) it is not When a widget is drawn or updated (typically with its `value` method) it is not
immediately displayed. To update the display `nanogui.refresh` is called: this immediately displayed. To update the display `nanogui.refresh` is called: this
enables multiple updates to the `framebuf` contents before once copying the enables multiple updates to the `FrameBuffer` contents before once copying the
buffer to the display. Postponement is for performance and provides a visually buffer to the display. Postponement enhances performance providing a visually
instant update. instant update.
Text components of widgets are rendered using the `Writer` (monochrome) or Text components of widgets are rendered using the `Writer` (monochrome) or
@ -393,10 +401,10 @@ then subsequently whenever a refresh is required. The method takes two args:
### 3.1.1 Setup file internals ### 3.1.1 Setup file internals
The file `color_setup.py` contains the hardware dependent code. It works as The file `color_setup.py` contains the hardware dependent code. It works as
described below, with the aim of allocating the `framebuf` before importing described below, with the aim of allocating the `FrameBuffer` before importing
other modules. This is intended to reduce the risk of memory failures. other modules. This is intended to reduce the risk of memory failures.
Firstly the file sets the display height and import the driver: Firstly the file sets the display height and imports the driver:
```python ```python
height = 96 # 1.27 inch 96*128 (rows*cols) display. Set to 128 for 1.5 inch height = 96 # 1.27 inch 96*128 (rows*cols) display. Set to 128 for 1.5 inch
import machine import machine
@ -461,27 +469,20 @@ If populating a label would cause it to extend beyond the screen boundary a
warning is printed at the console. The label may appear at an unexpected place. warning is printed at the console. The label may appear at an unexpected place.
The following is a complete "Hello world" script. The following is a complete "Hello world" script.
```python ```python
height = 96 # 1.27 inch 96*128 (rows*cols) display. Set to 128 for 1.5 inch from color_setup import ssd # Create a display instance
import machine
import gc
from drivers.ssd1351.ssd1351 import SSD1351 as SSD
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)
gc.collect() # Precaution before instantiating framebuf
ssd = SSD(spi, pcs, pdc, prst, height) # Create a display instance
from gui.core.nanogui import refresh from gui.core.nanogui import refresh
from gui.core.writer import CWriter
from gui.core.colors import *
from gui.widgets.label import Label from gui.widgets.label import Label
import gui.fonts.freesans20 as freesans20
refresh(ssd) # Initialise and clear display. refresh(ssd) # Initialise and clear display.
from gui.core.writer import CWriter # Import other modules
import gui.fonts.freesans20 as freesans20 # Font
GREEN = SSD.rgb(0, 255, 0) # Define colors
BLACK = 0
CWriter.set_textpos(ssd, 0, 0) # In case previous tests have altered it CWriter.set_textpos(ssd, 0, 0) # In case previous tests have altered it
wri = CWriter(ssd, freesans20, GREEN, BLACK, verbose=False) wri = CWriter(ssd, freesans20, GREEN, BLACK, verbose=False)
wri.set_clip(True, True, False) wri.set_clip(True, True, False)
# End of boilerplate code. This is our application:
# End of boilerplate code. This is our application:
Label(wri, 2, 2, 'Hello world!') Label(wri, 2, 2, 'Hello world!')
refresh(ssd) refresh(ssd)
``` ```
@ -807,11 +808,14 @@ the oldest (topmost) being discarded as required.
Device drivers capable of supporting `nanogui` can be extremely simple: see Device drivers capable of supporting `nanogui` can be extremely simple: see
`drivers/sharp/sharp.py` for a minimal example. It should be noted that the `drivers/sharp/sharp.py` for a minimal example. It should be noted that the
supplied device drivers are designed purely to support nanogui. To conserve RAM supplied device drivers are designed purely to support nanogui. To conserve RAM
they provide for the transfer of an external frame buffer to the device and they provide no functionality beyond the transfer of an external frame buffer
little else. Such a transfer typically takes a few tens of milliseconds. Many to the device. This transfer typically takes a few tens of milliseconds. While
driver chips support graphics primitives in hardware. In performance orientated visually instant, this period constitutes latency between an event occurring
applications such as games, drivers using these capabilities will be faster and a consequent display update. This may be unacceptable in applications such
than those provided here. as games. In such cases the `FrameBuffer` approach is inappropriate. Many
driver chips support graphics primitives in hardware; drivers using these
capabilities will be faster than those provided here and may often be found
using a forum search.
For a driver to support `nanogui` it must be subclassed from For a driver to support `nanogui` it must be subclassed from
`framebuf.FrameBuffer` and provide `height` and `width` bound variables being `framebuf.FrameBuffer` and provide `height` and `width` bound variables being
@ -823,9 +827,11 @@ the contents of the buffer underlying the `FrameBuffer` must be copied to the
hardware. hardware.
For color drivers, to conserve RAM it is suggested that 8-bit color is used For color drivers, to conserve RAM it is suggested that 8-bit color is used
for the `framebuf`. If the hardware does not support this, conversion to the for the `FrameBuffer`. If the hardware does not support this, conversion to the
supported color space needs to be done "on the fly" as per the SSD1351 driver. supported color space needs to be done "on the fly" as per the SSD1351 driver.
To maximise update speed consider using native, viper or assembler. This uses `framebuf.GS8` to stand in for 8 bit color in `rrrgggbb` format. To
maximise update speed consider using native, viper or assembler for the
conversion, typically to RGB565 format.
Color drivers should have a static method converting rgb(255, 255, 255) to a Color drivers should have a static method converting rgb(255, 255, 255) to a
form acceptable to the driver. For 8-bit rrrgggbb this can be: form acceptable to the driver. For 8-bit rrrgggbb this can be:

Wyświetl plik

@ -30,12 +30,9 @@ import gc
from drivers.st7735r.st7735r144 import ST7735R as SSD from drivers.st7735r.st7735r144 import ST7735R as SSD
height = 128
width = 128
pdc = machine.Pin('Y1', machine.Pin.OUT_PP, value=0) pdc = machine.Pin('Y1', machine.Pin.OUT_PP, value=0)
pcs = machine.Pin('Y2', machine.Pin.OUT_PP, value=1) pcs = machine.Pin('Y2', machine.Pin.OUT_PP, value=1)
prst = machine.Pin('Y3', machine.Pin.OUT_PP, value=1) prst = machine.Pin('Y3', machine.Pin.OUT_PP, value=1)
spi = machine.SPI(2, baudrate=12_000_000) spi = machine.SPI(2, baudrate=12_000_000)
gc.collect() # Precaution before instantiating framebuf gc.collect() # Precaution before instantiating framebuf
ssd = SSD(spi, pcs, pdc, prst, height, width) # Create a display instance ssd = SSD(spi, pcs, pdc, prst) # Create a display instance

Wyświetl plik

@ -29,12 +29,9 @@ import gc
from drivers.st7735r.st7735r import ST7735R as SSD from drivers.st7735r.st7735r import ST7735R as SSD
height = 128
width = 160
pdc = machine.Pin('Y1', machine.Pin.OUT_PP, value=0) pdc = machine.Pin('Y1', machine.Pin.OUT_PP, value=0)
pcs = machine.Pin('Y2', machine.Pin.OUT_PP, value=1) pcs = machine.Pin('Y2', machine.Pin.OUT_PP, value=1)
prst = machine.Pin('Y3', machine.Pin.OUT_PP, value=1) prst = machine.Pin('Y3', machine.Pin.OUT_PP, value=1)
spi = machine.SPI(2, baudrate=12_000_000) spi = machine.SPI(2, baudrate=12_000_000)
gc.collect() # Precaution before instantiating framebuf gc.collect() # Precaution before instantiating framebuf
ssd = SSD(spi, pcs, pdc, prst, height, width) # Create a display instance ssd = SSD(spi, pcs, pdc, prst) # Create a display instance

Wyświetl plik

@ -0,0 +1,15 @@
# Drivers for ST7735R
These are cross-platform but assume `micropython.viper` capability. They use
8-bit color to minimise the RAM used by the frame buffer.
* `st7735r.py` Supports [Adafruit 1.8" display](https://www.adafruit.com/product/358).
* `st7735r144.py` Supports [Adafruit 1.44" display](https://www.adafruit.com/product/2088).
Users of other ST7735R based displays should beware: there are many variants
with differing setup requirements.
[This driver](https://github.com/boochow/MicroPython-ST7735/blob/master/ST7735.py)
has four different initialisation routines for various display versions. Even
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.

Wyświetl plik

@ -1,4 +1,4 @@
# st7735r.py Driver for ST7735R LCD displays for nano-gui # st7735r.py Driver for 1.8" 128*160 ST7735R LCD displays for nano-gui
# Released under the MIT License (MIT). See LICENSE. # Released under the MIT License (MIT). See LICENSE.
# Copyright (c) 2018-2020 Peter Hinch # Copyright (c) 2018-2020 Peter Hinch
@ -12,6 +12,10 @@
# https://github.com/GuyCarver/MicroPython/blob/master/lib/ST7735.py # https://github.com/GuyCarver/MicroPython/blob/master/lib/ST7735.py
# https://github.com/boochow/MicroPython-ST7735 # https://github.com/boochow/MicroPython-ST7735
# https://learn.adafruit.com/adafruit-1-44-color-tft-with-micro-sd-socket/python-usage
# disp = st7735.ST7735R(spi, rotation=90, # 1.8" ST7735R
# disp = st7735.ST7735R(spi, rotation=270, height=128, x_offset=2, y_offset=3, # 1.44" ST7735R
from time import sleep_ms from time import sleep_ms
import framebuf import framebuf
import gc import gc
@ -19,7 +23,6 @@ import micropython
# Datasheet para 8.4 scl write cycle 66ns == 15MHz # Datasheet para 8.4 scl write cycle 66ns == 15MHz
# _lcopy: copy a line in 8 bit format to one in 12 bit RGB444. para 9.8.20. # _lcopy: copy a line in 8 bit format to one in 12 bit RGB444. para 9.8.20.
# 2 bytes become 3 in destination. Source format: # 2 bytes become 3 in destination. Source format:
# < D7 D6 D5 D4 D3 D2 D1 D0> # < D7 D6 D5 D4 D3 D2 D1 D0>
@ -48,7 +51,7 @@ class ST7735R(framebuf.FrameBuffer):
return (r & 0xe0) | ((g >> 3) & 0x1c) | (b >> 6) return (r & 0xe0) | ((g >> 3) & 0x1c) | (b >> 6)
# rst and cs are active low, SPI is mode 0 # rst and cs are active low, SPI is mode 0
def __init__(self, spi, cs, dc, rst, height, width): def __init__(self, spi, cs, dc, rst, height=128, width=160):
self._spi = spi self._spi = spi
self._rst = rst # Pins self._rst = rst # Pins
self._dc = dc self._dc = dc

Wyświetl plik

@ -1,4 +1,4 @@
# st7735r.py Driver for ST7735R LCD displays for nano-gui # st7735r144.py Driver for ST7735R 1.44" LCD display for nano-gui
# Released under the MIT License (MIT). See LICENSE. # Released under the MIT License (MIT). See LICENSE.
# Copyright (c) 2018-2020 Peter Hinch # Copyright (c) 2018-2020 Peter Hinch
@ -23,8 +23,15 @@ import micropython
# Datasheet para 8.4 scl write cycle 66ns == 15MHz # Datasheet para 8.4 scl write cycle 66ns == 15MHz
# _lcopy: copy a line in 8 bit format to one in 16 bit RGB565.
# 1 bytes becomes 2 in destination. Source format:
# < D7 D6 D5 D4 D3 D2 D1 D0>
# <R02 R01 R00 G02 G01 G00 B01 B00> <R12 R11 R10 G12 G11 G10 B11 B10>
# dest:
# <B01 B00 0 0 0 G02 G01 G00> <0 0 0 R02 R01 R00 0 0>
@micropython.viper @micropython.viper
def _lcopy(dest:ptr8, source:ptr8, length:int): # TODO check this def _lcopy(dest:ptr8, source:ptr8, length:int):
n = 0 n = 0
for x in range(length): for x in range(length):
c = source[x] c = source[x]
@ -34,29 +41,9 @@ def _lcopy(dest:ptr8, source:ptr8, length:int): # TODO check this
n += 1 n += 1
# _lcopy: copy a line in 8 bit format to one in 12 bit RGB444. para 9.8.20.
# 2 bytes become 3 in destination. Source format:
# < D7 D6 D5 D4 D3 D2 D1 D0>
# <R02 R01 R00 G02 G01 G00 B01 B00> <R12 R11 R10 G12 G11 G10 B11 B10>
# dest:
# <R02 R01 R00 0 G02 G01 G00 0> <B01 B00 0 0 R12 R11 R10 0> <G12 G11 G10 0 B11 B10 0 0>
@micropython.viper
def _lcopy12(dest:ptr8, source:ptr8, length:int):
n = 0
for x in range(0, length, 2):
c = source[x]
d = source[x + 1]
dest[n] = (c & 0xe0) | ((c & 0x1c) >> 1) # R0 G0
n += 1
dest[n] = ((c & 3) << 6) | ((d & 0xe0) >> 4) # B0 R1
n += 1
dest[n] = ((d & 0x1c) << 3) | ((d & 3) << 2) # G1 B1
n += 1
class ST7735R(framebuf.FrameBuffer): class ST7735R(framebuf.FrameBuffer):
# Convert r, g, b in range 0-255 to an 8 bit colour value # Convert r, g, b in range 0-255 to an 8 bit colour value
# rrrgggbb. Converted to 12 bit on the fly. # rrrgggbb. Converted to 16 bit on the fly.
@staticmethod @staticmethod
def rgb(r, g, b): def rgb(r, g, b):
return (r & 0xe0) | ((g >> 3) & 0x1c) | (b >> 6) return (r & 0xe0) | ((g >> 3) & 0x1c) | (b >> 6)
@ -75,7 +62,6 @@ class ST7735R(framebuf.FrameBuffer):
self.buffer = bytearray(self.height * self.width) self.buffer = bytearray(self.height * self.width)
self._mvb = memoryview(self.buffer) self._mvb = memoryview(self.buffer)
super().__init__(self.buffer, self.width, self.height, self.mode) super().__init__(self.buffer, self.width, self.height, self.mode)
#self._linebuf = bytearray(int(self.width * 3 // 2)) # 12 bit color out
self._linebuf = bytearray(self.width * 2) # 16 bit color out self._linebuf = bytearray(self.width * 2) # 16 bit color out
self._init() self._init()
self.show() self.show()
@ -132,71 +118,28 @@ class ST7735R(framebuf.FrameBuffer):
cmd(b'\x20') # INVOFF cmd(b'\x20') # INVOFF
# d7..d5 of MADCTL determine rotation/orientation # d7..d5 of MADCTL determine rotation/orientation
wcd(b'\x36', b'\xe0') # MADCTL: RGB landscape mode for 1.4" display wcd(b'\x36', b'\xe0') # MADCTL: RGB landscape mode for 1.4" display
#wcd(b'\x3a', b'\x03') # COLMOD 12 bit
wcd(b'\x3a', b'\x05') # COLMOD 16 bit wcd(b'\x3a', b'\x05') # COLMOD 16 bit
wcd(b'\xe0', b'\x02\x1c\x07\x12\x37\x32\x29\x2d\x29\x25\x2B\x39\x00\x01\x03\x10') # GMCTRP1 Gamma wcd(b'\xe0', b'\x02\x1c\x07\x12\x37\x32\x29\x2d\x29\x25\x2B\x39\x00\x01\x03\x10') # GMCTRP1 Gamma
wcd(b'\xe1', b'\x03\x1d\x07\x06\x2E\x2C\x29\x2D\x2E\x2E\x37\x3F\x00\x00\x02\x10') # GMCTRN1 wcd(b'\xe1', b'\x03\x1d\x07\x06\x2E\x2C\x29\x2D\x2E\x2E\x37\x3F\x00\x00\x02\x10') # GMCTRN1
#wcd(b'\x2a', int.to_bytes( 2 << 16 + self.width + 1, 4, 'big')) # CASET column address 0 start, 160/128 end wcd(b'\x2a', int.to_bytes((3 << 16) + self.width + 2, 4, 'big')) # CASET
#wcd(b'\x2b', int.to_bytes(3 << 16 + self.height + 2, 4, 'big')) # RASET wcd(b'\x2b', int.to_bytes((2 << 16) + self.height + 2, 4, 'big')) # RASET
cmd(b'\x13') # NORON cmd(b'\x13') # NORON
sleep_ms(10) sleep_ms(10)
cmd(b'\x29') # DISPON cmd(b'\x29') # DISPON
sleep_ms(100) sleep_ms(100)
def show(self): # Blocks 36ms on Pyboard D at stock frequency (160*128) def show(self): # Blocks 38.6ms on Pyboard D at stock frequency
wcd = self._wcd
wd = self.width wd = self.width
ht = self.height ht = self.height
lb = self._linebuf lb = self._linebuf
buf = self._mvb buf = self._mvb
start = 0 self._dc(0)
row = self.height - 1 self._cs(0)
while row >= 0: # For each line self._spi.write(b'\x2c') # RAMWR
self._dc(1)
for start in range(wd * (ht - 1), -1, - wd): # For each line
_lcopy(lb, buf[start :], wd) # Copy and map colors (68us) _lcopy(lb, buf[start :], wd) # Copy and map colors (68us)
wcd(b'\x2a', int.to_bytes((3 << 16) + 160, 4, 'big')) # CASET column address 3 start, 160 end self._spi.write(lb)
wcd(b'\x2b', int.to_bytes(((row + 2) << 16) + row + 3, 4, 'big')) # RASET self._cs(1)
wcd(b'\x2c', lb) # RAMWR
start += wd
row -= 1
#def show(self): # Blocks 36ms on Pyboard D at stock frequency (160*128)
#wd = self.width
#ht = self.height
#lb = self._linebuf
#buf = self._mvb
#self._dc(0)
#self._cs(0)
#self._spi.write(b'\x2c') # RAMWR
#self._dc(1)
#for start in range(wd * (ht - 1), -1, - wd): # For each line
#_lcopy(lb, buf[start :], wd) # Copy and map colors (68us)
#self._spi.write(lb)
#self._cs(1)
#import machine
#import gc
#from time import sleep_ms
#from drivers.st7735r.st7735r import ST7735R as SSD
#height = 128
#width = 128 # 160
#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, baudrate=12_000_000)
#gc.collect() # Precaution before instantiating framebuf
#ssd = SSD(spi, pcs, pdc, prst, height, width) # Create a display instance
#ssd.fill(0)
#ssd.show()
#sleep_ms(1000)
#ssd.line(0, 0, width - 1, height - 1, ssd.rgb(0, 255, 0)) # Green diagonal corner-to-corner
#ssd.rect(0, 0, 15, 15, ssd.rgb(255, 0, 0)) # Red square at top left
#ssd.show()
#sleep_ms(2000)
#ssd.fill(0)
#ssd.show()
#ssd.line(0, 0, width - 1, height - 1, ssd.rgb(0, 255, 255)) # Green diagonal corner-to-corner
#ssd.rect(0, 0, 40, 40, ssd.rgb(0, 0, 255)) # Blue square at top left
#ssd.show()

Wyświetl plik

@ -6,7 +6,7 @@
# Copyright (c) 2018-2020 Peter Hinch # Copyright (c) 2018-2020 Peter Hinch
# Initialise hardware and framebuf before importing modules. # Initialise hardware and framebuf before importing modules.
from color_setup import ssd, height # Create a display instance from color_setup import ssd # Create a display instance
from gui.core.nanogui import refresh from gui.core.nanogui import refresh
from gui.widgets.label import Label from gui.widgets.label import Label
from gui.widgets.dial import Dial, Pointer from gui.widgets.dial import Dial, Pointer