ili9341: st7735: st7789: unify rotation support

* Unify the Rotation type, so that SetRotation can be used in
    interfaces.
  * Add Rotation() method to these displays, so that the current
    rotation can be read.
  * Change SetRotation() so that it can return an error (if the given
    rotation isn't supported).
This commit is contained in:
Ayke van Laethem
2023-04-18 00:59:03 +02:00
committed by Ron Evans
parent 59d66d1e73
commit c689c11838
7 changed files with 96 additions and 53 deletions
+16
View File
@@ -12,3 +12,19 @@ type Displayer interface {
// Display sends the buffer (if any) to the screen. // Display sends the buffer (if any) to the screen.
Display() error Display() error
} }
// Rotation is how much a display has been rotated. Displays can be rotated, and
// sometimes also mirrored.
type Rotation uint8
// Clockwise rotation of the screen.
const (
Rotation0 = iota
Rotation90
Rotation180
Rotation270
Rotation0Mirror
Rotation90Mirror
Rotation180Mirror
Rotation270Mirror
)
+16 -6
View File
@@ -5,19 +5,21 @@ import (
"image/color" "image/color"
"machine" "machine"
"time" "time"
"tinygo.org/x/drivers"
) )
type Config struct { type Config struct {
Width int16 Width int16
Height int16 Height int16
Rotation Rotation Rotation drivers.Rotation
DisplayInversion bool DisplayInversion bool
} }
type Device struct { type Device struct {
width int16 width int16
height int16 height int16
rotation Rotation rotation drivers.Rotation
driver driver driver driver
x0, x1 int16 // cached address window; prevents useless/expensive x0, x1 int16 // cached address window; prevents useless/expensive
@@ -262,13 +264,20 @@ func (d *Device) Sleep(sleepEnabled bool) error {
return nil return nil
} }
// GetRotation returns the current rotation of the device // Rotation returns the current rotation of the device.
func (d *Device) GetRotation() Rotation { func (d *Device) Rotation() drivers.Rotation {
return d.rotation return d.rotation
} }
// SetRotation changes the rotation of the device (clock-wise) // GetRotation returns the current rotation of the device.
func (d *Device) SetRotation(rotation Rotation) { //
// Deprecated: use Rotation instead.
func (d *Device) GetRotation() drivers.Rotation {
return d.rotation
}
// SetRotation changes the rotation of the device (clock-wise).
func (d *Device) SetRotation(rotation drivers.Rotation) error {
madctl := uint8(0) madctl := uint8(0)
switch rotation % 8 { switch rotation % 8 {
case Rotation0: case Rotation0:
@@ -291,6 +300,7 @@ func (d *Device) SetRotation(rotation Rotation) {
cmdBuf[0] = madctl cmdBuf[0] = madctl
d.sendCommand(MADCTL, cmdBuf[:1]) d.sendCommand(MADCTL, cmdBuf[:1])
d.rotation = rotation d.rotation = rotation
return nil
} }
// SetScrollArea sets an area to scroll with fixed top/bottom or left/right parts of the display // SetScrollArea sets an area to scroll with fixed top/bottom or left/right parts of the display
+10 -8
View File
@@ -1,5 +1,7 @@
package ili9341 package ili9341
import "tinygo.org/x/drivers"
type Rotation uint8 type Rotation uint8
const ( const (
@@ -77,13 +79,13 @@ const (
) )
const ( const (
Rotation0 Rotation = 0 Rotation0 = drivers.Rotation0
Rotation90 Rotation = 1 // 90 degrees clock-wise rotation Rotation90 = drivers.Rotation90 // 90 degrees clock-wise rotation
Rotation180 Rotation = 2 Rotation180 = drivers.Rotation180
Rotation270 Rotation = 3 Rotation270 = drivers.Rotation270
Rotation0Mirror Rotation = 4 Rotation0Mirror = drivers.Rotation0Mirror
Rotation90Mirror Rotation = 5 Rotation90Mirror = drivers.Rotation90Mirror
Rotation180Mirror Rotation = 6 Rotation180Mirror = drivers.Rotation180Mirror
Rotation270Mirror Rotation = 7 Rotation270Mirror = drivers.Rotation270Mirror
) )
+6 -4
View File
@@ -1,5 +1,7 @@
package st7735 package st7735
import "tinygo.org/x/drivers"
// Registers // Registers
const ( const (
NOP = 0x00 NOP = 0x00
@@ -52,8 +54,8 @@ const (
GREENTAB Model = 0 GREENTAB Model = 0
MINI80x160 Model = 1 MINI80x160 Model = 1
NO_ROTATION Rotation = 0 NO_ROTATION = drivers.Rotation0
ROTATION_90 Rotation = 1 // 90 degrees clock-wise rotation ROTATION_90 = drivers.Rotation90 // 90 degrees clock-wise rotation
ROTATION_180 Rotation = 2 ROTATION_180 = drivers.Rotation180
ROTATION_270 Rotation = 3 ROTATION_270 = drivers.Rotation270
) )
+23 -16
View File
@@ -14,7 +14,11 @@ import (
) )
type Model uint8 type Model uint8
type Rotation uint8
// Rotation controls the rotation used by the display.
//
// Deprecated: use drivers.Rotation instead.
type Rotation = drivers.Rotation
var ( var (
errOutOfBounds = errors.New("rectangle coordinates outside display area") errOutOfBounds = errors.New("rectangle coordinates outside display area")
@@ -31,7 +35,7 @@ type Device struct {
height int16 height int16
columnOffset int16 columnOffset int16
rowOffset int16 rowOffset int16
rotation Rotation rotation drivers.Rotation
batchLength int16 batchLength int16
model Model model Model
isBGR bool isBGR bool
@@ -42,7 +46,7 @@ type Device struct {
type Config struct { type Config struct {
Width int16 Width int16
Height int16 Height int16
Rotation Rotation Rotation drivers.Rotation
Model Model Model Model
RowOffset int16 RowOffset int16
ColumnOffset int16 ColumnOffset int16
@@ -215,7 +219,7 @@ func (d *Device) SetPixel(x int16, y int16, c color.RGBA) {
// setWindow prepares the screen to be modified at a given rectangle // setWindow prepares the screen to be modified at a given rectangle
func (d *Device) setWindow(x, y, w, h int16) { func (d *Device) setWindow(x, y, w, h int16) {
if d.rotation == NO_ROTATION || d.rotation == ROTATION_180 { if d.rotation == drivers.Rotation0 || d.rotation == drivers.Rotation180 {
x += d.columnOffset x += d.columnOffset
y += d.rowOffset y += d.rowOffset
} else { } else {
@@ -345,35 +349,38 @@ func (d *Device) DrawFastHLine(x0, x1, y int16, c color.RGBA) {
// FillScreen fills the screen with a given color // FillScreen fills the screen with a given color
func (d *Device) FillScreen(c color.RGBA) { func (d *Device) FillScreen(c color.RGBA) {
if d.rotation == NO_ROTATION || d.rotation == ROTATION_180 { if d.rotation == drivers.Rotation0 || d.rotation == drivers.Rotation180 {
d.FillRectangle(0, 0, d.width, d.height, c) d.FillRectangle(0, 0, d.width, d.height, c)
} else { } else {
d.FillRectangle(0, 0, d.height, d.width, c) d.FillRectangle(0, 0, d.height, d.width, c)
} }
} }
// Rotation returns the currently configured rotation.
func (d *Device) Rotation() drivers.Rotation {
return d.rotation
}
// SetRotation changes the rotation of the device (clock-wise) // SetRotation changes the rotation of the device (clock-wise)
func (d *Device) SetRotation(rotation Rotation) { func (d *Device) SetRotation(rotation drivers.Rotation) error {
d.rotation = rotation
madctl := uint8(0) madctl := uint8(0)
switch rotation % 4 { switch rotation % 4 {
case 0: case drivers.Rotation0:
madctl = MADCTL_MX | MADCTL_MY madctl = MADCTL_MX | MADCTL_MY
break case drivers.Rotation90:
case 1:
madctl = MADCTL_MY | MADCTL_MV madctl = MADCTL_MY | MADCTL_MV
break case drivers.Rotation180:
case 2: // nothing to do
break case drivers.Rotation270:
case 3:
madctl = MADCTL_MX | MADCTL_MV madctl = MADCTL_MX | MADCTL_MV
break
} }
if d.isBGR { if d.isBGR {
madctl |= MADCTL_BGR madctl |= MADCTL_BGR
} }
d.Command(MADCTL) d.Command(MADCTL)
d.Data(madctl) d.Data(madctl)
return nil
} }
// Command sends a command to the display // Command sends a command to the display
@@ -394,7 +401,7 @@ func (d *Device) Tx(data []byte, isCommand bool) {
// Size returns the current size of the display. // Size returns the current size of the display.
func (d *Device) Size() (w, h int16) { func (d *Device) Size() (w, h int16) {
if d.rotation == NO_ROTATION || d.rotation == ROTATION_180 { if d.rotation == drivers.Rotation0 || d.rotation == drivers.Rotation180 {
return d.width, d.height return d.width, d.height
} }
return d.height, d.width return d.height, d.width
+6 -4
View File
@@ -1,5 +1,7 @@
package st7789 package st7789
import "tinygo.org/x/drivers"
// Registers // Registers
const ( const (
NOP = 0x00 NOP = 0x00
@@ -53,10 +55,10 @@ const (
VSCRDEF = 0x33 VSCRDEF = 0x33
VSCRSADD = 0x37 VSCRSADD = 0x37
NO_ROTATION Rotation = 0 NO_ROTATION = drivers.Rotation0
ROTATION_90 Rotation = 1 // 90 degrees clock-wise rotation ROTATION_90 = drivers.Rotation90 // 90 degrees clock-wise rotation
ROTATION_180 Rotation = 2 ROTATION_180 = drivers.Rotation180
ROTATION_270 Rotation = 3 ROTATION_270 = drivers.Rotation270
// Allowable frame rate codes for FRCTRL2 (Identifier is in Hz) // Allowable frame rate codes for FRCTRL2 (Identifier is in Hz)
FRAMERATE_111 FrameRate = 0x01 FRAMERATE_111 FrameRate = 0x01
+19 -15
View File
@@ -17,7 +17,9 @@ import (
) )
// Rotation controls the rotation used by the display. // Rotation controls the rotation used by the display.
type Rotation uint8 //
// Deprecated: use drivers.Rotation instead.
type Rotation = drivers.Rotation
// FrameRate controls the frame rate used by the display. // FrameRate controls the frame rate used by the display.
type FrameRate uint8 type FrameRate uint8
@@ -39,7 +41,7 @@ type Device struct {
rowOffsetCfg int16 rowOffsetCfg int16
columnOffset int16 columnOffset int16
rowOffset int16 rowOffset int16
rotation Rotation rotation drivers.Rotation
frameRate FrameRate frameRate FrameRate
batchLength int32 batchLength int32
isBGR bool isBGR bool
@@ -51,7 +53,7 @@ type Device struct {
type Config struct { type Config struct {
Width int16 Width int16
Height int16 Height int16
Rotation Rotation Rotation drivers.Rotation
RowOffset int16 RowOffset int16
ColumnOffset int16 ColumnOffset int16
FrameRate FrameRate FrameRate FrameRate
@@ -251,8 +253,8 @@ func (d *Device) Display() error {
// SetPixel sets a pixel in the screen // SetPixel sets a pixel in the screen
func (d *Device) SetPixel(x int16, y int16, c color.RGBA) { func (d *Device) SetPixel(x int16, y int16, c color.RGBA) {
if x < 0 || y < 0 || if x < 0 || y < 0 ||
(((d.rotation == NO_ROTATION || d.rotation == ROTATION_180) && (x >= d.width || y >= d.height)) || (((d.rotation == drivers.Rotation0 || d.rotation == drivers.Rotation180) && (x >= d.width || y >= d.height)) ||
((d.rotation == ROTATION_90 || d.rotation == ROTATION_270) && (x >= d.height || y >= d.width))) { ((d.rotation == drivers.Rotation90 || d.rotation == drivers.Rotation270) && (x >= d.height || y >= d.width))) {
return return
} }
d.FillRectangle(x, y, 1, 1, c) d.FillRectangle(x, y, 1, 1, c)
@@ -373,35 +375,37 @@ func (d *Device) FillScreen(c color.RGBA) {
} }
} }
// Rotation returns the current rotation of the device.
func (d *Device) Rotation() drivers.Rotation {
return d.rotation
}
// SetRotation changes the rotation of the device (clock-wise) // SetRotation changes the rotation of the device (clock-wise)
func (d *Device) SetRotation(rotation Rotation) { func (d *Device) SetRotation(rotation Rotation) error {
madctl := uint8(0) madctl := uint8(0)
switch rotation % 4 { switch rotation % 4 {
case 0: case drivers.Rotation0:
madctl = MADCTL_MX | MADCTL_MY madctl = MADCTL_MX | MADCTL_MY
d.rowOffset = d.rowOffsetCfg d.rowOffset = d.rowOffsetCfg
d.columnOffset = d.columnOffsetCfg d.columnOffset = d.columnOffsetCfg
break case drivers.Rotation90:
case 1:
madctl = MADCTL_MY | MADCTL_MV madctl = MADCTL_MY | MADCTL_MV
d.rowOffset = d.columnOffsetCfg d.rowOffset = d.columnOffsetCfg
d.columnOffset = d.rowOffsetCfg d.columnOffset = d.rowOffsetCfg
break case drivers.Rotation180:
case 2:
d.rowOffset = 0 d.rowOffset = 0
d.columnOffset = 0 d.columnOffset = 0
break case drivers.Rotation270:
case 3:
madctl = MADCTL_MX | MADCTL_MV madctl = MADCTL_MX | MADCTL_MV
d.rowOffset = 0 d.rowOffset = 0
d.columnOffset = 0 d.columnOffset = 0
break
} }
if d.isBGR { if d.isBGR {
madctl |= MADCTL_BGR madctl |= MADCTL_BGR
} }
d.Command(MADCTL) d.Command(MADCTL)
d.Data(madctl) d.Data(madctl)
return nil
} }
// Command sends a command to the display. // Command sends a command to the display.
@@ -442,7 +446,7 @@ func (d *Device) Rx(command uint8, data []byte) {
// Size returns the current size of the display. // Size returns the current size of the display.
func (d *Device) Size() (w, h int16) { func (d *Device) Size() (w, h int16) {
if d.rotation == NO_ROTATION || d.rotation == ROTATION_180 { if d.rotation == drivers.Rotation0 || d.rotation == drivers.Rotation180 {
return d.width, d.height return d.width, d.height
} }
return d.height, d.width return d.height, d.width