mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-20 06:28:59 +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 {
|
type Config struct {
|
||||||
Width int16
|
Width int16 // Width is the display resolution
|
||||||
Height int16
|
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 {
|
type Device struct {
|
||||||
@@ -22,12 +24,16 @@ type Device struct {
|
|||||||
dc machine.Pin
|
dc machine.Pin
|
||||||
rst machine.Pin
|
rst machine.Pin
|
||||||
busy machine.Pin
|
busy machine.Pin
|
||||||
|
logicalWidth int16
|
||||||
width int16
|
width int16
|
||||||
height int16
|
height int16
|
||||||
buffer []uint8
|
buffer []uint8
|
||||||
bufferLength uint32
|
bufferLength uint32
|
||||||
|
rotation Rotation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Rotation uint8
|
||||||
|
|
||||||
// Look up table for full updates
|
// Look up table for full updates
|
||||||
var lutFullUpdate = [30]uint8{
|
var lutFullUpdate = [30]uint8{
|
||||||
0x22, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x11,
|
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.
|
// Configure sets up the device.
|
||||||
func (d *Device) Configure(cfg Config) {
|
func (d *Device) Configure(cfg Config) {
|
||||||
|
if cfg.LogicalWidth != 0 {
|
||||||
|
d.logicalWidth = cfg.LogicalWidth
|
||||||
|
} else {
|
||||||
|
d.logicalWidth = 128
|
||||||
|
}
|
||||||
if cfg.Width != 0 {
|
if cfg.Width != 0 {
|
||||||
d.width = cfg.Width
|
d.width = cfg.Width
|
||||||
} else {
|
} else {
|
||||||
d.width = 128
|
d.width = 122
|
||||||
}
|
}
|
||||||
if cfg.Height != 0 {
|
if cfg.Height != 0 {
|
||||||
d.height = cfg.Height
|
d.height = cfg.Height
|
||||||
} else {
|
} else {
|
||||||
d.height = 250
|
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)
|
d.buffer = make([]uint8, d.bufferLength)
|
||||||
for i := uint32(0); i < d.bufferLength; i++ {
|
for i := uint32(0); i < d.bufferLength; i++ {
|
||||||
d.buffer[i] = 0xFF
|
d.buffer[i] = 0xFF
|
||||||
@@ -158,10 +170,11 @@ func (d *Device) SetLUT(fullUpdate bool) {
|
|||||||
// We use RGBA(0,0,0, 255) as white (transparent)
|
// We use RGBA(0,0,0, 255) as white (transparent)
|
||||||
// Anything else as black
|
// Anything else as black
|
||||||
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 || 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
|
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
|
if c.R == 0 && c.G == 0 && c.B == 0 { // TRANSPARENT / WHITE
|
||||||
d.buffer[byteIndex] |= 0x80 >> uint8(x%8)
|
d.buffer[byteIndex] |= 0x80 >> uint8(x%8)
|
||||||
} else { // WHITE / EMPTY
|
} 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.
|
// Display sends the buffer to the screen.
|
||||||
func (d *Device) Display() error {
|
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++ {
|
for j := int16(0); j < d.height; j++ {
|
||||||
d.setMemoryPointer(0, j)
|
d.setMemoryPointer(0, j)
|
||||||
d.SendCommand(WRITE_RAM)
|
d.SendCommand(WRITE_RAM)
|
||||||
for i := int16(0); i < d.width/8; i++ {
|
for i := int16(0); i < d.logicalWidth/8; i++ {
|
||||||
d.SendData(d.buffer[i+j*(d.width/8)])
|
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.
|
// 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 {
|
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")
|
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
|
x &= 0xF8
|
||||||
width &= 0xF8
|
width &= 0xF8
|
||||||
width = x + width // reuse variables
|
width = x + width // reuse variables
|
||||||
if width >= d.width {
|
if width >= d.logicalWidth {
|
||||||
width = d.width
|
width = d.logicalWidth
|
||||||
}
|
}
|
||||||
height = y + height
|
height = y + height
|
||||||
if height > d.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.setMemoryPointer(8*x, y)
|
||||||
d.SendCommand(WRITE_RAM)
|
d.SendCommand(WRITE_RAM)
|
||||||
for i := int16(x); i < width; i++ {
|
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
|
// ClearDisplay erases the device SRAM
|
||||||
func (d *Device) ClearDisplay() {
|
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.setMemoryPointer(0, 0)
|
||||||
d.SendCommand(WRITE_RAM)
|
d.SendCommand(WRITE_RAM)
|
||||||
for i := uint32(0); i < d.bufferLength; i++ {
|
for i := uint32(0); i < d.bufferLength; i++ {
|
||||||
@@ -274,5 +300,28 @@ func (d *Device) ClearBuffer() {
|
|||||||
|
|
||||||
// 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) {
|
||||||
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_X_ADDRESS_COUNTER = 0x4E
|
||||||
SET_RAM_Y_ADDRESS_COUNTER = 0x4F
|
SET_RAM_Y_ADDRESS_COUNTER = 0x4F
|
||||||
TERMINATE_FRAME_READ_WRITE = 0xFF
|
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