kopia lustrzana https://github.com/peterhinch/micropython-nano-gui
ST7735r 1.44 inch drivers: enable rotation.
rodzic
4d0c1c4dd1
commit
059d9c3705
59
DRIVERS.md
59
DRIVERS.md
|
@ -191,9 +191,15 @@ def spi_init(spi):
|
|||
# 4. 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).
|
||||
8-bit or 4-bit color to minimise the RAM used by the frame buffer.
|
||||
|
||||
Drivers for [Adafruit 1.8" display](https://www.adafruit.com/product/358).
|
||||
* `st7735r.py` 8-bit color.
|
||||
* `st7735r_4bit.py` 4-bit color for further RAM reduction.
|
||||
|
||||
For [Adafruit 1.44" display](https://www.adafruit.com/product/2088).
|
||||
* `st7735r144.py` 8-bit color.
|
||||
* `st7735r144_4bit` 4 bit color.
|
||||
|
||||
Users of other ST7735R based displays should beware: there are many variants
|
||||
with differing setup requirements.
|
||||
|
@ -208,7 +214,7 @@ 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:
|
||||
#### ST7735R Constructor args 1.8" display:
|
||||
* `spi` An initialised SPI bus instance. The device can support clock rates of
|
||||
upto 15MHz.
|
||||
* `cs` An initialised output pin. Initial value should be 1.
|
||||
|
@ -219,12 +225,29 @@ soft SPI may be used but hard may be faster.
|
|||
* `width=160`
|
||||
* `usd=False` Upside down: set `True` to invert display.
|
||||
* `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:
|
||||
the SPI bus. See below.
|
||||
|
||||
#### ST7735R144 Constructor args 1.44" display:
|
||||
* `spi` An initialised SPI bus instance. The device can support clock rates of
|
||||
upto 15MHz.
|
||||
* `cs` An initialised output pin. Initial value should be 1.
|
||||
* `dc` An initialised output pin. Initial value should be 0.
|
||||
* `rst` An initialised output pin. Initial value should be 1.
|
||||
* `height=128` Display dimensions in pixels.
|
||||
* `width=128`
|
||||
* `rotation=0` Pass 0, 90, 180 or 270 to rotate the display.
|
||||
* `init_spi=False` This optional arg enables flexible options in configuring
|
||||
the SPI bus. See below.
|
||||
|
||||
#### The init_spi constructor arg
|
||||
|
||||
The `False` default assumes exclusive access to the bus. It is initialised by
|
||||
`color_setup.py` and those settings are 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 which caters for the case where another
|
||||
program may have changed the baudrate:
|
||||
```python
|
||||
def spi_init(spi):
|
||||
spi.init(baudrate=12_000_000) # Data sheet: max is 12MHz
|
||||
|
@ -531,8 +554,18 @@ long as `.rgb()` and the "on the fly" converter match, this is arbitrary.
|
|||
The `Writer` (monochrome) or `CWriter` (color) classes and the `nanogui` module
|
||||
should then work automatically.
|
||||
|
||||
Drivers for displays using I2C may need to use
|
||||
[I2C.writevto](http://docs.micropython.org/en/latest/library/machine.I2C.html?highlight=writevto#machine.I2C.writevto)
|
||||
depending on the chip requirements.
|
||||
The following script is useful for testing color display drivers after
|
||||
configuring `color_setup.py`. It draws squares at the extreme corners of the
|
||||
display and a corner to corner diagonal.
|
||||
```python
|
||||
from color_setup import ssd # Create a display instance
|
||||
from gui.core.nanogui import refresh
|
||||
refresh(ssd, True) # Initialise and clear display.
|
||||
ssd.fill(0)
|
||||
ssd.line(0, 0, ssd.width - 1, ssd.height - 1, ssd.rgb(0, 255, 0)) # Green diagonal
|
||||
ssd.rect(0, 0, 15, 15, ssd.rgb(255, 0, 0)) # Red square at top left
|
||||
ssd.rect(ssd.width -15, ssd.height -15, 15, 15, ssd.rgb(0, 0, 255)) # Blue square at bottm right
|
||||
ssd.show()
|
||||
```
|
||||
|
||||
###### [Contents](./DRIVERS.md#contents)
|
||||
|
|
|
@ -49,7 +49,7 @@ class ST7735R(framebuf.FrameBuffer):
|
|||
return (r & 0xe0) | ((g >> 3) & 0x1c) | (b >> 6)
|
||||
|
||||
# rst and cs are active low, SPI is mode 0
|
||||
def __init__(self, spi, cs, dc, rst, height=128, width=128, init_spi=False):
|
||||
def __init__(self, spi, cs, dc, rst, height=128, width=128, rotation=0, init_spi=False):
|
||||
self._spi = spi
|
||||
self._rst = rst # Pins
|
||||
self._dc = dc
|
||||
|
@ -63,7 +63,11 @@ class ST7735R(framebuf.FrameBuffer):
|
|||
self._mvb = memoryview(buf)
|
||||
super().__init__(buf, self.width, self.height, mode)
|
||||
self._linebuf = bytearray(self.width * 2) # 16 bit color out
|
||||
self._init()
|
||||
quad, mod = divmod(rotation, 90) # Get quadrant
|
||||
if mod or quad > 3:
|
||||
quad %= 4
|
||||
print('Warning: rotation adjusted to', quad * 90)
|
||||
self._init(quad)
|
||||
self.show()
|
||||
|
||||
# Hardware reset
|
||||
|
@ -95,7 +99,7 @@ class ST7735R(framebuf.FrameBuffer):
|
|||
self._cs(1)
|
||||
|
||||
# Initialise the hardware. Blocks 500ms.
|
||||
def _init(self):
|
||||
def _init(self, quad):
|
||||
self._hwreset() # Hardware reset. Blocks 3ms
|
||||
if self._spi_init: # A callback was passed
|
||||
self._spi_init(self._spi) # Bus may be shared
|
||||
|
@ -119,13 +123,18 @@ class ST7735R(framebuf.FrameBuffer):
|
|||
|
||||
cmd(b'\x20') # INVOFF
|
||||
# d7..d5 of MADCTL determine rotation/orientation
|
||||
wcd(b'\x36', b'\xe0') # MADCTL: RGB landscape mode for 1.4" display
|
||||
# (MADCTL_DATA, ColumnOffset, RowOffset)
|
||||
rval, co, ro = ((b'\x20', 1, 2),
|
||||
(b'\x40', 2, 1),
|
||||
(b'\xe0', 3, 2),
|
||||
(b'\x80', 2, 3))[quad]
|
||||
wcd(b'\x36', rval) # MADCTL: rotation mode for 1.44" display
|
||||
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'\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((3 << 16) + self.width + 2, 4, 'big')) # CASET
|
||||
wcd(b'\x2b', int.to_bytes((2 << 16) + self.height + 2, 4, 'big')) # RASET
|
||||
wcd(b'\x2a', int.to_bytes((co << 16) + self.width + co - 1, 4, 'big')) # CASET
|
||||
wcd(b'\x2b', int.to_bytes((ro << 16) + self.height + ro - 1, 4, 'big')) # RASET
|
||||
|
||||
cmd(b'\x13') # NORON
|
||||
sleep_ms(10)
|
||||
|
|
|
@ -52,7 +52,7 @@ class ST7735R(framebuf.FrameBuffer):
|
|||
return (r & 0xf8) << 5 | (g & 0x1c) << 11 | (g & 0xe0) >> 5 | (b & 0xf8)
|
||||
|
||||
# rst and cs are active low, SPI is mode 0
|
||||
def __init__(self, spi, cs, dc, rst, height=128, width=128, init_spi=False):
|
||||
def __init__(self, spi, cs, dc, rst, height=128, width=128, rotation=0, init_spi=False):
|
||||
self._spi = spi
|
||||
self._rst = rst # Pins
|
||||
self._dc = dc
|
||||
|
@ -66,7 +66,11 @@ class ST7735R(framebuf.FrameBuffer):
|
|||
self._mvb = memoryview(buf)
|
||||
super().__init__(buf, self.width, self.height, mode)
|
||||
self._linebuf = bytearray(self.width * 2) # 16 bit color out
|
||||
self._init()
|
||||
quad, mod = divmod(rotation, 90) # Get quadrant
|
||||
if mod or quad > 3:
|
||||
quad %= 4
|
||||
print('Warning: rotation adjusted to', quad * 90)
|
||||
self._init(quad)
|
||||
self.show()
|
||||
|
||||
# Hardware reset
|
||||
|
@ -98,7 +102,7 @@ class ST7735R(framebuf.FrameBuffer):
|
|||
self._cs(1)
|
||||
|
||||
# Initialise the hardware. Blocks 500ms.
|
||||
def _init(self):
|
||||
def _init(self, quad):
|
||||
self._hwreset() # Hardware reset. Blocks 3ms
|
||||
if self._spi_init: # A callback was passed
|
||||
self._spi_init(self._spi) # Bus may be shared
|
||||
|
@ -122,13 +126,18 @@ class ST7735R(framebuf.FrameBuffer):
|
|||
|
||||
cmd(b'\x20') # INVOFF
|
||||
# d7..d5 of MADCTL determine rotation/orientation
|
||||
wcd(b'\x36', b'\xe0') # MADCTL: RGB landscape mode for 1.4" display
|
||||
# (MADCTL_DATA, ColumnOffset, RowOffset)
|
||||
rval, co, ro = ((b'\x20', 1, 2),
|
||||
(b'\x40', 2, 1),
|
||||
(b'\xe0', 3, 2),
|
||||
(b'\x80', 2, 3))[quad]
|
||||
wcd(b'\x36', rval) # MADCTL: rotation mode for 1.44" display
|
||||
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'\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((3 << 16) + self.width + 2, 4, 'big')) # CASET
|
||||
wcd(b'\x2b', int.to_bytes((2 << 16) + self.height + 2, 4, 'big')) # RASET
|
||||
wcd(b'\x2a', int.to_bytes((co << 16) + self.width + co - 1, 4, 'big')) # CASET
|
||||
wcd(b'\x2b', int.to_bytes((ro << 16) + self.height + ro - 1, 4, 'big')) # RASET
|
||||
|
||||
cmd(b'\x13') # NORON
|
||||
sleep_ms(10)
|
||||
|
|
Ładowanie…
Reference in New Issue