kopia lustrzana https://github.com/peterhinch/micropython-nano-gui
ILI9488: Add code comments re SPI clock rate.
rodzic
8fbb4b7474
commit
843d153f8f
|
@ -2,7 +2,7 @@
|
|||
|
||||
### Based on ili9486.py by Peter Hinch.
|
||||
### Retaining his copyright
|
||||
#
|
||||
|
||||
# Copyright (c) Peter Hinch 2022-2025
|
||||
# Released under the MIT license see LICENSE
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
|||
# You must use this driver only when using the ILI9488 SPI
|
||||
# interface. It will send 3 bytes per pixel.
|
||||
|
||||
# ILI9488 max SPI baudrate 20MHz (datasheet 17.4.3) but 24MHz is a reasonable overclock.
|
||||
|
||||
from time import sleep_ms
|
||||
import gc
|
||||
|
@ -26,21 +27,21 @@ from drivers.boolpalette import BoolPalette
|
|||
# small performance improvement.
|
||||
# greyscale
|
||||
@micropython.viper
|
||||
def _lcopy_gs(dest: ptr8, source: ptr8, length: int) :
|
||||
def _lcopy_gs(dest: ptr8, source: ptr8, length: int):
|
||||
# rgb666 - 18bit/pixel
|
||||
n: int = length * 6 - 1
|
||||
while length:
|
||||
length -= 1
|
||||
c : uint = source[length]
|
||||
c: uint = source[length]
|
||||
# Store the index in the 4 high order bits
|
||||
p : uint = c & 0xF0 # current pixel
|
||||
q : uint = c << 4 # next pixel
|
||||
p: uint = c & 0xF0 # current pixel
|
||||
q: uint = c << 4 # next pixel
|
||||
|
||||
dest[n] = q
|
||||
n -= 1
|
||||
dest[n] = q
|
||||
n -= 1
|
||||
dest[n] = q
|
||||
dest[n] = q
|
||||
n -= 1
|
||||
|
||||
dest[n] = p
|
||||
|
@ -50,18 +51,19 @@ def _lcopy_gs(dest: ptr8, source: ptr8, length: int) :
|
|||
dest[n] = p
|
||||
n -= 1
|
||||
|
||||
|
||||
# Do processing from end to beginning for
|
||||
# small performance improvement.
|
||||
# color
|
||||
@micropython.viper
|
||||
def _lcopy(dest: ptr8, source: ptr8, lut: ptr16, length: int) :
|
||||
def _lcopy(dest: ptr8, source: ptr8, lut: ptr16, length: int):
|
||||
# Convert lut rgb 565 to rgb666
|
||||
n: int = length * 6 - 1
|
||||
n: int = length * 6 - 1
|
||||
while length:
|
||||
length -= 1
|
||||
c : uint = source[length]
|
||||
c: uint = source[length]
|
||||
|
||||
v = lut[c & 0x0F] # next pixel
|
||||
v = lut[c & 0x0F] # next pixel
|
||||
dest[n] = (v & 0x001F) << 3 # B
|
||||
n -= 1
|
||||
dest[n] = (v & 0x07E0) >> 3 # G
|
||||
|
@ -69,7 +71,7 @@ def _lcopy(dest: ptr8, source: ptr8, lut: ptr16, length: int) :
|
|||
dest[n] = (v & 0xF800) >> 8 # R
|
||||
n -= 1
|
||||
|
||||
v : uint = lut[c >> 4] # current pixel
|
||||
v: uint = lut[c >> 4] # current pixel
|
||||
dest[n] = (v & 0x001F) << 3 # B
|
||||
n -= 1
|
||||
dest[n] = (v & 0x07E0) >> 3 # G
|
||||
|
@ -77,6 +79,7 @@ def _lcopy(dest: ptr8, source: ptr8, lut: ptr16, length: int) :
|
|||
dest[n] = (v & 0xF800) >> 8 # R
|
||||
n -= 1
|
||||
|
||||
|
||||
class ILI9488(framebuf.FrameBuffer):
|
||||
|
||||
lut = bytearray(32)
|
||||
|
@ -91,8 +94,17 @@ class ILI9488(framebuf.FrameBuffer):
|
|||
|
||||
# Transpose width & height for landscape mode
|
||||
def __init__(
|
||||
self, spi, cs, dc, rst, height=320, width=480, usd=False, mirror=False, init_spi=False,
|
||||
lines_per_write=4
|
||||
self,
|
||||
spi,
|
||||
cs,
|
||||
dc,
|
||||
rst,
|
||||
height=320,
|
||||
width=480,
|
||||
usd=False,
|
||||
mirror=False,
|
||||
init_spi=False,
|
||||
lines_per_write=4,
|
||||
):
|
||||
self._spi = spi
|
||||
self._cs = cs
|
||||
|
@ -108,14 +120,14 @@ class ILI9488(framebuf.FrameBuffer):
|
|||
#
|
||||
# lines_per_write must divide evenly into height
|
||||
#
|
||||
if (self.height % lines_per_write) != 0 :
|
||||
raise ValueError('lines_per_write invalid')
|
||||
self._lines_per_write=lines_per_write
|
||||
if (self.height % lines_per_write) != 0:
|
||||
raise ValueError("lines_per_write invalid")
|
||||
self._lines_per_write = lines_per_write
|
||||
gc.collect()
|
||||
buf = bytearray(height * width // 2)
|
||||
self.mvb = memoryview(buf)
|
||||
super().__init__(buf, width, height, self.mode) # Logical aspect ratio
|
||||
self._linebuf = bytearray(self._lines_per_write*self.width * 3)
|
||||
self._linebuf = bytearray(self._lines_per_write * self.width * 3)
|
||||
|
||||
# Hardware reset
|
||||
self._rst(0)
|
||||
|
@ -136,14 +148,14 @@ class ILI9488(framebuf.FrameBuffer):
|
|||
self._wcd(b"\x2a", int.to_bytes(self.width - 1, 4, "big"))
|
||||
self._wcd(b"\x2b", int.to_bytes(self.height - 1, 4, "big")) # SET_PAGE ht
|
||||
|
||||
if self.width > self.height :
|
||||
if self.width > self.height:
|
||||
# landscape
|
||||
madctl = 0xe8 if usd else 0x28
|
||||
else :
|
||||
#portrait
|
||||
madctl = 0xE8 if usd else 0x28
|
||||
else:
|
||||
# portrait
|
||||
madctl = 0x48 if usd else 0x88
|
||||
if mirror:
|
||||
madctl ^= 0x80 # toggle MY
|
||||
madctl ^= 0x80 # toggle MY
|
||||
self._wcd(b"\x36", madctl.to_bytes(1, "big")) # MADCTL: RGB portrait mode
|
||||
self._wcmd(b"\x11") # sleep out
|
||||
self._wcmd(b"\x29") # display on
|
||||
|
@ -184,18 +196,18 @@ class ILI9488(framebuf.FrameBuffer):
|
|||
wd = self.width >> 1
|
||||
ht = self.height
|
||||
spi_write = self._spi.write
|
||||
length = self._lines_per_write*wd
|
||||
length = self._lines_per_write * wd
|
||||
r = range(0, wd * ht, length)
|
||||
if cm :
|
||||
lcopy = _lcopy_gs # Copy greyscale
|
||||
for start in r : # For each line
|
||||
lcopy(lb, buf[start:], length)
|
||||
if cm:
|
||||
lcopy = _lcopy_gs # Copy greyscale
|
||||
for start in r: # For each line
|
||||
lcopy(lb, buf[start:], length)
|
||||
spi_write(lb)
|
||||
else :
|
||||
else:
|
||||
clut = ILI9488.lut
|
||||
lcopy = _lcopy # Copy and map colors
|
||||
for start in r : # For each line
|
||||
lcopy(lb, buf[start:], clut, length)
|
||||
for start in r: # For each line
|
||||
lcopy(lb, buf[start:], clut, length)
|
||||
spi_write(lb)
|
||||
self._cs(1)
|
||||
|
||||
|
@ -213,8 +225,11 @@ class ILI9488(framebuf.FrameBuffer):
|
|||
lines, mod = divmod(self.height, split) # Lines per segment
|
||||
if mod:
|
||||
raise ValueError("Invalid do_refresh arg 'split'")
|
||||
if lines % self._lines_per_write != 0 :
|
||||
raise ValueError("Invalid do_refresh arg 'split' for lines_per_write of %d" %(self._lines_per_write))
|
||||
if lines % self._lines_per_write != 0:
|
||||
raise ValueError(
|
||||
"Invalid do_refresh arg 'split' for lines_per_write of %d"
|
||||
% (self._lines_per_write)
|
||||
)
|
||||
clut = ILI9488.lut
|
||||
lb = self._linebuf
|
||||
buf = self.mvb
|
||||
|
@ -224,7 +239,7 @@ class ILI9488(framebuf.FrameBuffer):
|
|||
wd = self.width // 2
|
||||
line = 0
|
||||
spi_write = self._spi.write
|
||||
length = self._lines_per_write*wd
|
||||
length = self._lines_per_write * wd
|
||||
for _ in range(split): # For each segment
|
||||
async with elock:
|
||||
if self._spi_init: # A callback was passed
|
||||
|
@ -232,14 +247,14 @@ class ILI9488(framebuf.FrameBuffer):
|
|||
self._cs(0)
|
||||
r = range(wd * line, wd * (line + lines), length)
|
||||
if cm:
|
||||
lcopy = _lcopy_gs # Copy and greyscale
|
||||
for start in r :
|
||||
lcopy(lb, buf[start:], length)
|
||||
lcopy = _lcopy_gs # Copy and greyscale
|
||||
for start in r:
|
||||
lcopy(lb, buf[start:], length)
|
||||
spi_write(lb)
|
||||
else :
|
||||
lcopy = _lcopy # Copy and map colors
|
||||
for start in r :
|
||||
lcopy(lb, buf[start:], clut, length)
|
||||
else:
|
||||
lcopy = _lcopy # Copy and map colors
|
||||
for start in r:
|
||||
lcopy(lb, buf[start:], clut, length)
|
||||
spi_write(lb)
|
||||
|
||||
line += lines
|
||||
|
|
|
@ -8,16 +8,16 @@ from micropython import const
|
|||
# Modify these Pin assignments to match your hardware.
|
||||
|
||||
# Simple GPIO's
|
||||
LCD_DC = const(21) # PICO Pin 27
|
||||
LCD_RST = const(22) # PICO Pin 29
|
||||
LCD_CS = const(27) # PICO Pin 32
|
||||
LCD_DC = const(21) # PICO Pin 27
|
||||
LCD_RST = const(22) # PICO Pin 29
|
||||
LCD_CS = const(27) # PICO Pin 32
|
||||
LCD_BackLight = const(28) # PICO Pin 34
|
||||
|
||||
# SPI pins
|
||||
|
||||
LCD_CLK = const(18) # PICO Pin 24
|
||||
LCD_MOSI = const(19) # PICO Pin 25
|
||||
LCD_MISO = const(16) # PICO Pin 21
|
||||
LCD_CLK = const(18) # PICO Pin 24
|
||||
LCD_MOSI = const(19) # PICO Pin 25
|
||||
LCD_MISO = const(16) # PICO Pin 21
|
||||
|
||||
from machine import Pin, SPI
|
||||
from drivers.ili94xx.ili9488 import ILI9488 as SSD
|
||||
|
@ -26,14 +26,17 @@ from drivers.ili94xx.ili9488 import ILI9488 as SSD
|
|||
# (Create and export an SSD instance)
|
||||
|
||||
prst = Pin(LCD_RST, Pin.OUT, value=1)
|
||||
pdc = Pin(LCD_DC, Pin.OUT, value=1)
|
||||
pcs = Pin(LCD_CS, Pin.OUT, value=1)
|
||||
pdc = Pin(LCD_DC, Pin.OUT, value=1)
|
||||
pcs = Pin(LCD_CS, Pin.OUT, value=1)
|
||||
|
||||
# turn on back light
|
||||
backlight=Pin(LCD_BackLight, Pin.OUT, value=1)
|
||||
backlight = Pin(LCD_BackLight, Pin.OUT, value=1)
|
||||
|
||||
# Use SPI bus 0, 24 Mhz is maximum speed on PICO
|
||||
spi = SPI(0, 24_000_000, sck=Pin(LCD_CLK), mosi=Pin(LCD_MOSI, Pin.OUT), miso=Pin(LCD_MISO, Pin.OUT))
|
||||
# This is an overclock of the ILI9488 - see driver code comment.
|
||||
spi = SPI(
|
||||
0, 24_000_000, sck=Pin(LCD_CLK), mosi=Pin(LCD_MOSI, Pin.OUT), miso=Pin(LCD_MISO, Pin.OUT)
|
||||
)
|
||||
|
||||
# Precaution before instantiating framebuf
|
||||
ssd = SSD(spi, height=480, width=320, dc=pdc, cs=pcs, rst=prst, usd=False)
|
||||
|
|
Ładowanie…
Reference in New Issue