epd2in13: added rotation

This commit is contained in:
Daniel Esteban
2019-06-30 16:07:12 +02:00
committed by Ayke van Laethem
parent 28dbbe2e65
commit d8675515bc
2 changed files with 69 additions and 15 deletions
+64 -15
View File
@@ -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
} }
+5
View File
@@ -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
) )