mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-06 07:53:41 +00:00
epd2in13: added rotation
This commit is contained in:
committed by
Ayke van Laethem
parent
28dbbe2e65
commit
d8675515bc
@@ -12,8 +12,10 @@ import (
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Width int16
|
||||
Height int16
|
||||
Width int16 // Width is the display resolution
|
||||
Height int16
|
||||
LogicalWidth int16 // LogicalWidth must be a multiple of 8 and same size or bigger than Width
|
||||
Rotation Rotation // Rotation is clock-wise
|
||||
}
|
||||
|
||||
type Device struct {
|
||||
@@ -22,12 +24,16 @@ type Device struct {
|
||||
dc machine.Pin
|
||||
rst machine.Pin
|
||||
busy machine.Pin
|
||||
logicalWidth int16
|
||||
width int16
|
||||
height int16
|
||||
buffer []uint8
|
||||
bufferLength uint32
|
||||
rotation Rotation
|
||||
}
|
||||
|
||||
type Rotation uint8
|
||||
|
||||
// Look up table for full updates
|
||||
var lutFullUpdate = [30]uint8{
|
||||
0x22, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x11,
|
||||
@@ -61,17 +67,23 @@ func New(bus machine.SPI, csPin, dcPin, rstPin, busyPin machine.Pin) Device {
|
||||
|
||||
// Configure sets up the device.
|
||||
func (d *Device) Configure(cfg Config) {
|
||||
if cfg.LogicalWidth != 0 {
|
||||
d.logicalWidth = cfg.LogicalWidth
|
||||
} else {
|
||||
d.logicalWidth = 128
|
||||
}
|
||||
if cfg.Width != 0 {
|
||||
d.width = cfg.Width
|
||||
} else {
|
||||
d.width = 128
|
||||
d.width = 122
|
||||
}
|
||||
if cfg.Height != 0 {
|
||||
d.height = cfg.Height
|
||||
} else {
|
||||
d.height = 250
|
||||
}
|
||||
d.bufferLength = (uint32(d.width) * uint32(d.height)) / 8
|
||||
d.rotation = cfg.Rotation
|
||||
d.bufferLength = (uint32(d.logicalWidth) * uint32(d.height)) / 8
|
||||
d.buffer = make([]uint8, d.bufferLength)
|
||||
for i := uint32(0); i < d.bufferLength; i++ {
|
||||
d.buffer[i] = 0xFF
|
||||
@@ -158,10 +170,11 @@ func (d *Device) SetLUT(fullUpdate bool) {
|
||||
// We use RGBA(0,0,0, 255) as white (transparent)
|
||||
// Anything else as black
|
||||
func (d *Device) SetPixel(x int16, y int16, c color.RGBA) {
|
||||
if x < 0 || x >= d.width || y < 0 || y >= d.height {
|
||||
x, y = d.xy(x, y)
|
||||
if x < 0 || x >= d.logicalWidth || y < 0 || y >= d.height {
|
||||
return
|
||||
}
|
||||
byteIndex := (x + y*d.width) / 8
|
||||
byteIndex := (x + y*d.logicalWidth) / 8
|
||||
if c.R == 0 && c.G == 0 && c.B == 0 { // TRANSPARENT / WHITE
|
||||
d.buffer[byteIndex] |= 0x80 >> uint8(x%8)
|
||||
} else { // WHITE / EMPTY
|
||||
@@ -171,12 +184,12 @@ func (d *Device) SetPixel(x int16, y int16, c color.RGBA) {
|
||||
|
||||
// Display sends the buffer to the screen.
|
||||
func (d *Device) Display() error {
|
||||
d.setMemoryArea(0, 0, d.width-1, d.height-1)
|
||||
d.setMemoryArea(0, 0, d.logicalWidth-1, d.height-1)
|
||||
for j := int16(0); j < d.height; j++ {
|
||||
d.setMemoryPointer(0, j)
|
||||
d.SendCommand(WRITE_RAM)
|
||||
for i := int16(0); i < d.width/8; i++ {
|
||||
d.SendData(d.buffer[i+j*(d.width/8)])
|
||||
for i := int16(0); i < d.logicalWidth/8; i++ {
|
||||
d.SendData(d.buffer[i+j*(d.logicalWidth/8)])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,15 +201,28 @@ func (d *Device) Display() error {
|
||||
}
|
||||
|
||||
// DisplayRect sends only an area of the buffer to the screen.
|
||||
// The rectangle points need to be a multiple of 8 in the screen.
|
||||
// They might not work as expected if the screen is rotated.
|
||||
func (d *Device) DisplayRect(x int16, y int16, width int16, height int16) error {
|
||||
if x < 0 || y < 0 || x >= d.width || y >= d.height || width < 0 || height < 0 {
|
||||
x, y = d.xy(x, y)
|
||||
if x < 0 || y < 0 || x >= d.logicalWidth || y >= d.height || width < 0 || height < 0 {
|
||||
return errors.New("wrong rectangle")
|
||||
}
|
||||
if d.rotation == ROTATION_90 {
|
||||
width, height = height, width
|
||||
x -= width
|
||||
} else if d.rotation == ROTATION_180 {
|
||||
x -= width - 1
|
||||
y -= height - 1
|
||||
} else if d.rotation == ROTATION_270 {
|
||||
width, height = height, width
|
||||
y -= height
|
||||
}
|
||||
x &= 0xF8
|
||||
width &= 0xF8
|
||||
width = x + width // reuse variables
|
||||
if width >= d.width {
|
||||
width = d.width
|
||||
if width >= d.logicalWidth {
|
||||
width = d.logicalWidth
|
||||
}
|
||||
height = y + height
|
||||
if height > d.height {
|
||||
@@ -209,7 +235,7 @@ func (d *Device) DisplayRect(x int16, y int16, width int16, height int16) error
|
||||
d.setMemoryPointer(8*x, y)
|
||||
d.SendCommand(WRITE_RAM)
|
||||
for i := int16(x); i < width; i++ {
|
||||
d.SendData(d.buffer[i+y*d.width/8])
|
||||
d.SendData(d.buffer[i+y*d.logicalWidth/8])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,7 +248,7 @@ func (d *Device) DisplayRect(x int16, y int16, width int16, height int16) error
|
||||
|
||||
// ClearDisplay erases the device SRAM
|
||||
func (d *Device) ClearDisplay() {
|
||||
d.setMemoryArea(0, 0, d.width-1, d.height-1)
|
||||
d.setMemoryArea(0, 0, d.logicalWidth-1, d.height-1)
|
||||
d.setMemoryPointer(0, 0)
|
||||
d.SendCommand(WRITE_RAM)
|
||||
for i := uint32(0); i < d.bufferLength; i++ {
|
||||
@@ -274,5 +300,28 @@ func (d *Device) ClearBuffer() {
|
||||
|
||||
// Size returns the current size of the display.
|
||||
func (d *Device) Size() (w, h int16) {
|
||||
return d.width, d.height
|
||||
if d.rotation == ROTATION_90 || d.rotation == ROTATION_270 {
|
||||
return d.height, d.logicalWidth
|
||||
}
|
||||
return d.logicalWidth, d.height
|
||||
}
|
||||
|
||||
// SetRotation changes the rotation (clock-wise) of the device
|
||||
func (d *Device) SetRotation(rotation Rotation) {
|
||||
d.rotation = rotation
|
||||
}
|
||||
|
||||
// xy chages the coordinates according to the rotation
|
||||
func (d *Device) xy(x, y int16) (int16, int16) {
|
||||
switch d.rotation {
|
||||
case NO_ROTATION:
|
||||
return x, y
|
||||
case ROTATION_90:
|
||||
return d.width - y - 1, x
|
||||
case ROTATION_180:
|
||||
return d.width - x - 1, d.height - y - 1
|
||||
case ROTATION_270:
|
||||
return y, d.height - x - 1
|
||||
}
|
||||
return x, y
|
||||
}
|
||||
|
||||
@@ -23,4 +23,9 @@ const (
|
||||
SET_RAM_X_ADDRESS_COUNTER = 0x4E
|
||||
SET_RAM_Y_ADDRESS_COUNTER = 0x4F
|
||||
TERMINATE_FRAME_READ_WRITE = 0xFF
|
||||
|
||||
NO_ROTATION Rotation = 0
|
||||
ROTATION_90 Rotation = 1 // 90 degrees clock-wise rotation
|
||||
ROTATION_180 Rotation = 2
|
||||
ROTATION_270 Rotation = 3
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user