From deca190ba2ff3acb12871645034d2ae5053c6747 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Wed, 12 Apr 2023 20:26:18 +0200 Subject: [PATCH] ili9341: add EnableTEOutput to be able to sync drawing with VSYNC Many displays don't have the TE pin exposed. But those that do have the pin (for example, the PyPortal) can use it to synchronize writing a new image to the display. When implemented correctly, tearing can be avoided entirely. This commit also changes the LCD refresh direction to either top-to-bottom or left-to-right depending on the rotation. Previously it might refresh from right-to-left or bottom-to-top. This has little impact on code that doesn't use the TE line, but code that does now only needs to worry about two cases (top-to-bottom and left-to-right) instead of four. (Unfortunately, it appears that the hardware doesn't support changing the major LCD refresh order so code that wants to do tear-free rendering still needs to care about these two cases). --- ili9341/ili9341.go | 22 +++++++++++++++++----- ili9341/registers.go | 2 ++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/ili9341/ili9341.go b/ili9341/ili9341.go index 2b6f58c..4b8f133 100644 --- a/ili9341/ili9341.go +++ b/ili9341/ili9341.go @@ -160,6 +160,18 @@ func (d *Device) Display() error { return nil } +// EnableTEOutput enables the TE ("tearing effect") line. +// The TE line goes high when the screen is not currently being updated and can +// be used to start drawing. When used correctly, it can avoid tearing entirely. +func (d *Device) EnableTEOutput(on bool) { + if on { + cmdBuf[0] = 0 + d.sendCommand(TEON, cmdBuf[:1]) // M=0 (V-blanking only, no H-blanking) + } else { + d.sendCommand(TEOFF, nil) // TEOFF + } +} + // DrawRGBBitmap copies an RGB bitmap to the internal buffer at given coordinates func (d *Device) DrawRGBBitmap(x, y int16, data []uint16, w, h int16) error { k, i := d.Size() @@ -287,17 +299,17 @@ func (d *Device) SetRotation(rotation drivers.Rotation) error { case Rotation90: madctl = MADCTL_MV | MADCTL_BGR case Rotation180: - madctl = MADCTL_MY | MADCTL_BGR + madctl = MADCTL_MY | MADCTL_BGR | MADCTL_ML case Rotation270: - madctl = MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR + madctl = MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR | MADCTL_ML case Rotation0Mirror: madctl = MADCTL_BGR case Rotation90Mirror: - madctl = MADCTL_MY | MADCTL_MV | MADCTL_BGR + madctl = MADCTL_MY | MADCTL_MV | MADCTL_BGR | MADCTL_ML case Rotation180Mirror: - madctl = MADCTL_MX | MADCTL_MY | MADCTL_BGR + madctl = MADCTL_MX | MADCTL_MY | MADCTL_BGR | MADCTL_ML case Rotation270Mirror: - madctl = MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR + madctl = MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR | MADCTL_ML } cmdBuf[0] = madctl d.sendCommand(MADCTL, cmdBuf[:1]) diff --git a/ili9341/registers.go b/ili9341/registers.go index 6b56c6c..6457461 100644 --- a/ili9341/registers.go +++ b/ili9341/registers.go @@ -41,6 +41,8 @@ const ( PTLAR = 0x30 ///< Partial Area VSCRDEF = 0x33 ///< Vertical Scrolling Definition + TEOFF = 0x34 ///< TEOFF: Tearing Effect Line OFF + TEON = 0x35 ///< TEON: Tearing Effect Line ON MADCTL = 0x36 ///< Memory Access Control VSCRSADD = 0x37 ///< Vertical Scrolling Start Address PIXFMT = 0x3A ///< COLMOD: Pixel Format Set