From 7e3e54275b76f44ba9317855a613d2740a1bee42 Mon Sep 17 00:00:00 2001 From: George Sexton Date: Fri, 4 Apr 2025 14:25:54 -0600 Subject: [PATCH 01/14] Fixes --- inky/impression.go | 41 ++++++++++++++++++++++++++++++++++------- inky/inky.go | 11 +++++++++++ 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/inky/impression.go b/inky/impression.go index 840d337..2c54739 100644 --- a/inky/impression.go +++ b/inky/impression.go @@ -17,6 +17,7 @@ import ( "periph.io/x/conn/v3" "periph.io/x/conn/v3/display" "periph.io/x/conn/v3/gpio" + "periph.io/x/conn/v3/gpio/gpioreg" "periph.io/x/conn/v3/physic" "periph.io/x/conn/v3/spi" ) @@ -155,7 +156,11 @@ func NewImpression(p spi.Port, dc gpio.PinOut, reset gpio.PinOut, busy gpio.PinI if o.Model == IMPRESSION73 { cSpeed = acSpeed } - c, err := p.Connect(cSpeed, spi.Mode0, cs0Pin) + // The SPI driver has a max buffer size of 4K bytes, but our image size + // is 192K Bytes. To make the Impression 7.3 treat this as single trans- + // action, we have to take over control of the CS pin and manipulate it + // as required. + c, err := p.Connect(cSpeed, spi.Mode0|spi.NoCS, cs0Pin) if err != nil { return nil, fmt.Errorf("failed to connect to inky over spi: %v", err) } @@ -186,6 +191,7 @@ func NewImpression(p spi.Port, dc gpio.PinOut, reset gpio.PinOut, busy gpio.PinI model: o.Model, variant: o.DisplayVariant, pcbVariant: o.PCBVariant, + cs: gpioreg.ByName("GPIO8"), }, saturation: 50, // Looks good enough for most of the images. } @@ -521,11 +527,12 @@ func (d *DevImpression) updateAC(pix []uint8) error { // TODO there has to be a better way to force the white colour to be used instead of clear... buf := make([]byte, len(pix)) for i := range pix { - if pix[i]&0xF == 7 { - buf[i] = (pix[i] & 0xF0) + 1 + buf[i] = pix[i] + if buf[i]&0xF == 7 { + buf[i] = (buf[i] & 0xF0) + 1 } - if pix[i]&0xF0 == 0x70 { - buf[i] = (pix[i] & 0xF) + 0x10 + if buf[i]&0xF0 == 0x70 { + buf[i] = (buf[i] & 0xF) + 0x10 } } @@ -558,8 +565,28 @@ func (d *DevImpression) wait(dur time.Duration) { log.Printf("Err: %s", err) return } + if d.busy.Read() == gpio.High { + time.Sleep(dur) + return + } // Wait for rising edges (Low -> High) or the timeout. - d.busy.WaitForEdge(dur) + tEnd := time.Now().Add(dur) + edgeDur := dur + for tEnd.After(time.Now()) { + // Debounce the edge + edge := d.busy.WaitForEdge(edgeDur) + if edge { + // The python driver is using 10ms debounce period + time.Sleep(10 * time.Millisecond) + l := d.busy.Read() + if l { + // It's still high. Return + return + } + // It was a bounce. Recalculate the duration to wait for the edge. + edgeDur = tEnd.Sub(time.Now()) + } + } } // ColorModel returns the device native color model. @@ -589,7 +616,7 @@ func (d *DevImpression) Set(x, y int, c color.Color) { // Draw updates the display with the image. func (d *DevImpression) Draw(r image.Rectangle, src image.Image, sp image.Point) error { if r != d.Bounds() { - return fmt.Errorf("partial updates are not supported") + return fmt.Errorf("partial updates are not supported r=%#v bounds=%#v", r, d.Bounds()) } if src.Bounds() != d.Bounds() { diff --git a/inky/inky.go b/inky/inky.go index 4012017..4dc029b 100644 --- a/inky/inky.go +++ b/inky/inky.go @@ -14,6 +14,7 @@ import ( "periph.io/x/conn/v3" "periph.io/x/conn/v3/display" "periph.io/x/conn/v3/gpio" + "periph.io/x/conn/v3/gpio/gpioreg" "periph.io/x/conn/v3/physic" "periph.io/x/conn/v3/spi" ) @@ -65,6 +66,7 @@ type Dev struct { variant uint // PCB Variant of the panel. Represents a version string as a number (12 -> 1.2). pcbVariant uint + cs gpio.PinOut } // New opens a handle to an Inky pHAT or wHAT. @@ -99,6 +101,7 @@ func New(p spi.Port, dc gpio.PinOut, reset gpio.PinOut, busy gpio.PinIn, o *Opts model: o.Model, variant: o.DisplayVariant, pcbVariant: o.PCBVariant, + cs: gpioreg.ByName("GPIO8"), } switch o.Model { @@ -337,12 +340,14 @@ func (d *Dev) reset() (err error) { } func (d *Dev) sendCommand(command byte, data []byte) error { + d.cs.Out(gpio.Low) if err := d.dc.Out(gpio.Low); err != nil { return err } if err := d.c.Tx([]byte{command}, nil); err != nil { return fmt.Errorf("failed to send command %x to inky: %v", command, err) } + d.cs.Out(gpio.High) if data != nil { if err := d.sendData(data); err != nil { return fmt.Errorf("failed to send data for command %x to inky: %v", command, err) @@ -352,9 +357,12 @@ func (d *Dev) sendCommand(command byte, data []byte) error { } func (d *Dev) sendData(data []byte) error { + d.cs.Out(gpio.Low) + if err := d.dc.Out(gpio.High); err != nil { return err } + for len(data) != 0 { var chunk []byte if len(data) > d.maxTxSize { @@ -366,6 +374,9 @@ func (d *Dev) sendData(data []byte) error { return fmt.Errorf("failed to send data to inky: %v", err) } } + + d.cs.Out(gpio.High) + return nil } From bc639221ca38113eea7d300e184c6f53e2b91b7c Mon Sep 17 00:00:00 2001 From: George Sexton Date: Fri, 4 Apr 2025 14:42:10 -0600 Subject: [PATCH 02/14] Fix incorrect usage. a 'pin number' was passed to port.Connect(), when that parameter is actually the bit count. --- inky/impression.go | 4 ++-- inky/inky.go | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/inky/impression.go b/inky/impression.go index 2c54739..0acd72a 100644 --- a/inky/impression.go +++ b/inky/impression.go @@ -160,7 +160,7 @@ func NewImpression(p spi.Port, dc gpio.PinOut, reset gpio.PinOut, busy gpio.PinI // is 192K Bytes. To make the Impression 7.3 treat this as single trans- // action, we have to take over control of the CS pin and manipulate it // as required. - c, err := p.Connect(cSpeed, spi.Mode0|spi.NoCS, cs0Pin) + c, err := p.Connect(cSpeed, spi.Mode0|spi.NoCS, 8) if err != nil { return nil, fmt.Errorf("failed to connect to inky over spi: %v", err) } @@ -191,7 +191,7 @@ func NewImpression(p spi.Port, dc gpio.PinOut, reset gpio.PinOut, busy gpio.PinI model: o.Model, variant: o.DisplayVariant, pcbVariant: o.PCBVariant, - cs: gpioreg.ByName("GPIO8"), + cs: gpioreg.ByName(cs0Pin), }, saturation: 50, // Looks good enough for most of the images. } diff --git a/inky/inky.go b/inky/inky.go index 4dc029b..6cdd610 100644 --- a/inky/inky.go +++ b/inky/inky.go @@ -23,7 +23,7 @@ var _ display.Drawer = &Dev{} var _ conn.Resource = &Dev{} const ( - cs0Pin = 8 + cs0Pin = "GPIO8" ) var borderColor = map[Color]byte{ @@ -75,7 +75,7 @@ func New(p spi.Port, dc gpio.PinOut, reset gpio.PinOut, busy gpio.PinIn, o *Opts return nil, fmt.Errorf("unsupported color: %v", o.ModelColor) } - c, err := p.Connect(488*physic.KiloHertz, spi.Mode0, cs0Pin) + c, err := p.Connect(488*physic.KiloHertz, spi.Mode0 | spi.NoCS, 8) if err != nil { return nil, fmt.Errorf("failed to connect to inky over spi: %v", err) } @@ -101,7 +101,7 @@ func New(p spi.Port, dc gpio.PinOut, reset gpio.PinOut, busy gpio.PinIn, o *Opts model: o.Model, variant: o.DisplayVariant, pcbVariant: o.PCBVariant, - cs: gpioreg.ByName("GPIO8"), + cs: gpioreg.ByName(cs0Pin), } switch o.Model { From bca1c90b5eb3022317089458f868c13265276546 Mon Sep 17 00:00:00 2001 From: George Sexton Date: Fri, 4 Apr 2025 14:42:28 -0600 Subject: [PATCH 03/14] Fix incorrect usage. a 'pin number' was passed to port.Connect(), when that parameter is actually the bit count. --- inky/inky.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inky/inky.go b/inky/inky.go index 6cdd610..0c10537 100644 --- a/inky/inky.go +++ b/inky/inky.go @@ -75,7 +75,7 @@ func New(p spi.Port, dc gpio.PinOut, reset gpio.PinOut, busy gpio.PinIn, o *Opts return nil, fmt.Errorf("unsupported color: %v", o.ModelColor) } - c, err := p.Connect(488*physic.KiloHertz, spi.Mode0 | spi.NoCS, 8) + c, err := p.Connect(488*physic.KiloHertz, spi.Mode0|spi.NoCS, 8) if err != nil { return nil, fmt.Errorf("failed to connect to inky over spi: %v", err) } From 9f3eb67a7b8a4e6236df819e929fcad5c1c3242f Mon Sep 17 00:00:00 2001 From: George Sexton Date: Fri, 4 Apr 2025 14:51:23 -0600 Subject: [PATCH 04/14] fix error handling --- inky/inky.go | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/inky/inky.go b/inky/inky.go index 0c10537..51f3e97 100644 --- a/inky/inky.go +++ b/inky/inky.go @@ -333,33 +333,41 @@ func (d *Dev) reset() (err error) { } }() if err := d.sendCommand(0x12, nil); err != nil { // Soft Reset - return fmt.Errorf("failed to reset inky: %v", err) + return fmt.Errorf("inky: failed to reset inky: %v", err) } d.busy.WaitForEdge(-1) return } -func (d *Dev) sendCommand(command byte, data []byte) error { - d.cs.Out(gpio.Low) - if err := d.dc.Out(gpio.Low); err != nil { +func (d *Dev) sendCommand(command byte, data []byte) (err error) { + err = d.cs.Out(gpio.Low) + if err != nil { return err } - if err := d.c.Tx([]byte{command}, nil); err != nil { - return fmt.Errorf("failed to send command %x to inky: %v", command, err) + if err = d.dc.Out(gpio.Low); err != nil { + return + } + if err = d.c.Tx([]byte{command}, nil); err != nil { + err = fmt.Errorf("inky: failed to send command %x to inky: %v", command, err) + return } d.cs.Out(gpio.High) if data != nil { - if err := d.sendData(data); err != nil { - return fmt.Errorf("failed to send data for command %x to inky: %v", command, err) + if err = d.sendData(data); err != nil { + err = fmt.Errorf("inky: failed to send data for command %x to inky: %v", command, err) + return } } - return nil + return } -func (d *Dev) sendData(data []byte) error { - d.cs.Out(gpio.Low) +func (d *Dev) sendData(data []byte) (err error) { + err = d.cs.Out(gpio.Low) + if err != nil { + return + } - if err := d.dc.Out(gpio.High); err != nil { + if err = d.dc.Out(gpio.High); err != nil { return err } @@ -370,14 +378,15 @@ func (d *Dev) sendData(data []byte) error { } else { chunk, data = data, nil } - if err := d.c.Tx(chunk, nil); err != nil { - return fmt.Errorf("failed to send data to inky: %v", err) + if err = d.c.Tx(chunk, nil); err != nil { + err = fmt.Errorf("inky: failed to send data to inky: %v", err) + return } } - d.cs.Out(gpio.High) + err = d.cs.Out(gpio.High) - return nil + return } func pack(bits []bool) ([]byte, error) { From 405e04ef6e485f12473e632bb4e36b998763bec7 Mon Sep 17 00:00:00 2001 From: George Sexton Date: Fri, 4 Apr 2025 14:54:32 -0600 Subject: [PATCH 05/14] missed handling one error --- inky/inky.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/inky/inky.go b/inky/inky.go index 51f3e97..baae0d8 100644 --- a/inky/inky.go +++ b/inky/inky.go @@ -351,7 +351,11 @@ func (d *Dev) sendCommand(command byte, data []byte) (err error) { err = fmt.Errorf("inky: failed to send command %x to inky: %v", command, err) return } - d.cs.Out(gpio.High) + err = d.cs.Out(gpio.High) + if err != nil { + return err + } + if data != nil { if err = d.sendData(data); err != nil { err = fmt.Errorf("inky: failed to send data for command %x to inky: %v", command, err) From 31fd0334573aa920a8d1dce3d28a5b698643804f Mon Sep 17 00:00:00 2001 From: George Sexton Date: Fri, 4 Apr 2025 14:59:55 -0600 Subject: [PATCH 06/14] More lint fixes --- inky/impression.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inky/impression.go b/inky/impression.go index 0acd72a..ce5a880 100644 --- a/inky/impression.go +++ b/inky/impression.go @@ -584,7 +584,7 @@ func (d *DevImpression) wait(dur time.Duration) { return } // It was a bounce. Recalculate the duration to wait for the edge. - edgeDur = tEnd.Sub(time.Now()) + edgeDur = time.Until(tEnd) } } } From e27ed10928ea27eac62013d7273f9fff09544e73 Mon Sep 17 00:00:00 2001 From: George Sexton Date: Fri, 4 Apr 2025 15:21:55 -0600 Subject: [PATCH 07/14] Add Multi color parsing to types --- inky/types.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/inky/types.go b/inky/types.go index 466d7c9..83f4535 100644 --- a/inky/types.go +++ b/inky/types.go @@ -69,6 +69,8 @@ func (c *Color) Set(s string) error { *c = Yellow case "white": *c = White + case "multi": + *c = Multi default: return fmt.Errorf("unknown color %q: expected either black, red, yellow or white", s) } From b4f2e163f953b1ea4bc4dcd82e09ba7c2739d156 Mon Sep 17 00:00:00 2001 From: George Sexton Date: Sat, 5 Apr 2025 10:26:49 -0600 Subject: [PATCH 08/14] Remove manual manipulation of CS since it isn't required. --- inky/impression.go | 4 +--- inky/inky.go | 24 +----------------------- 2 files changed, 2 insertions(+), 26 deletions(-) diff --git a/inky/impression.go b/inky/impression.go index ce5a880..fff1b4d 100644 --- a/inky/impression.go +++ b/inky/impression.go @@ -17,7 +17,6 @@ import ( "periph.io/x/conn/v3" "periph.io/x/conn/v3/display" "periph.io/x/conn/v3/gpio" - "periph.io/x/conn/v3/gpio/gpioreg" "periph.io/x/conn/v3/physic" "periph.io/x/conn/v3/spi" ) @@ -160,7 +159,7 @@ func NewImpression(p spi.Port, dc gpio.PinOut, reset gpio.PinOut, busy gpio.PinI // is 192K Bytes. To make the Impression 7.3 treat this as single trans- // action, we have to take over control of the CS pin and manipulate it // as required. - c, err := p.Connect(cSpeed, spi.Mode0|spi.NoCS, 8) + c, err := p.Connect(cSpeed, spi.Mode0, 8) if err != nil { return nil, fmt.Errorf("failed to connect to inky over spi: %v", err) } @@ -191,7 +190,6 @@ func NewImpression(p spi.Port, dc gpio.PinOut, reset gpio.PinOut, busy gpio.PinI model: o.Model, variant: o.DisplayVariant, pcbVariant: o.PCBVariant, - cs: gpioreg.ByName(cs0Pin), }, saturation: 50, // Looks good enough for most of the images. } diff --git a/inky/inky.go b/inky/inky.go index baae0d8..07eee29 100644 --- a/inky/inky.go +++ b/inky/inky.go @@ -14,7 +14,6 @@ import ( "periph.io/x/conn/v3" "periph.io/x/conn/v3/display" "periph.io/x/conn/v3/gpio" - "periph.io/x/conn/v3/gpio/gpioreg" "periph.io/x/conn/v3/physic" "periph.io/x/conn/v3/spi" ) @@ -22,10 +21,6 @@ import ( var _ display.Drawer = &Dev{} var _ conn.Resource = &Dev{} -const ( - cs0Pin = "GPIO8" -) - var borderColor = map[Color]byte{ Black: 0x00, Red: 0x73, @@ -66,7 +61,6 @@ type Dev struct { variant uint // PCB Variant of the panel. Represents a version string as a number (12 -> 1.2). pcbVariant uint - cs gpio.PinOut } // New opens a handle to an Inky pHAT or wHAT. @@ -75,7 +69,7 @@ func New(p spi.Port, dc gpio.PinOut, reset gpio.PinOut, busy gpio.PinIn, o *Opts return nil, fmt.Errorf("unsupported color: %v", o.ModelColor) } - c, err := p.Connect(488*physic.KiloHertz, spi.Mode0|spi.NoCS, 8) + c, err := p.Connect(488*physic.KiloHertz, spi.Mode0, 8) if err != nil { return nil, fmt.Errorf("failed to connect to inky over spi: %v", err) } @@ -101,7 +95,6 @@ func New(p spi.Port, dc gpio.PinOut, reset gpio.PinOut, busy gpio.PinIn, o *Opts model: o.Model, variant: o.DisplayVariant, pcbVariant: o.PCBVariant, - cs: gpioreg.ByName(cs0Pin), } switch o.Model { @@ -340,10 +333,6 @@ func (d *Dev) reset() (err error) { } func (d *Dev) sendCommand(command byte, data []byte) (err error) { - err = d.cs.Out(gpio.Low) - if err != nil { - return err - } if err = d.dc.Out(gpio.Low); err != nil { return } @@ -351,10 +340,6 @@ func (d *Dev) sendCommand(command byte, data []byte) (err error) { err = fmt.Errorf("inky: failed to send command %x to inky: %v", command, err) return } - err = d.cs.Out(gpio.High) - if err != nil { - return err - } if data != nil { if err = d.sendData(data); err != nil { @@ -366,11 +351,6 @@ func (d *Dev) sendCommand(command byte, data []byte) (err error) { } func (d *Dev) sendData(data []byte) (err error) { - err = d.cs.Out(gpio.Low) - if err != nil { - return - } - if err = d.dc.Out(gpio.High); err != nil { return err } @@ -388,8 +368,6 @@ func (d *Dev) sendData(data []byte) (err error) { } } - err = d.cs.Out(gpio.High) - return } From 49a6b37ab94cbfbf7350f44ee3997dc5654d1e24 Mon Sep 17 00:00:00 2001 From: George Sexton Date: Sat, 5 Apr 2025 17:32:45 -0600 Subject: [PATCH 09/14] Rework the send commands to be compatible with SPI control of CS, or manual control. --- inky/impression.go | 7 +++++++ inky/inky.go | 51 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/inky/impression.go b/inky/impression.go index fff1b4d..b4ae44d 100644 --- a/inky/impression.go +++ b/inky/impression.go @@ -17,6 +17,7 @@ import ( "periph.io/x/conn/v3" "periph.io/x/conn/v3/display" "periph.io/x/conn/v3/gpio" + "periph.io/x/conn/v3/gpio/gpioreg" "periph.io/x/conn/v3/physic" "periph.io/x/conn/v3/spi" ) @@ -177,6 +178,11 @@ func NewImpression(p spi.Port, dc gpio.PinOut, reset gpio.PinOut, busy gpio.PinI maxTxSize = 4096 // Use a conservative default. } } + // If possible, grab the CS pin. + cs := gpioreg.ByName(cs0Pin) + if cs != nil && cs.Out(csDisabled) != nil { + cs = nil + } d := &DevImpression{ Dev: Dev{ @@ -190,6 +196,7 @@ func NewImpression(p spi.Port, dc gpio.PinOut, reset gpio.PinOut, busy gpio.PinI model: o.Model, variant: o.DisplayVariant, pcbVariant: o.PCBVariant, + cs: cs, }, saturation: 50, // Looks good enough for most of the images. } diff --git a/inky/inky.go b/inky/inky.go index 07eee29..9499c70 100644 --- a/inky/inky.go +++ b/inky/inky.go @@ -14,6 +14,7 @@ import ( "periph.io/x/conn/v3" "periph.io/x/conn/v3/display" "periph.io/x/conn/v3/gpio" + "periph.io/x/conn/v3/gpio/gpioreg" "periph.io/x/conn/v3/physic" "periph.io/x/conn/v3/spi" ) @@ -28,6 +29,12 @@ var borderColor = map[Color]byte{ White: 0x31, } +const ( + cs0Pin = "GPIO8" + csEnabled = gpio.Low + csDisabled = gpio.High +) + // Dev is a handle to an Inky. type Dev struct { c conn.Conn @@ -61,6 +68,8 @@ type Dev struct { variant uint // PCB Variant of the panel. Represents a version string as a number (12 -> 1.2). pcbVariant uint + // cs is the chip-select pin for SPI. Refer to setCSPin() for information. + cs gpio.PinOut } // New opens a handle to an Inky pHAT or wHAT. @@ -83,7 +92,11 @@ func New(p spi.Port, dc gpio.PinOut, reset gpio.PinOut, busy gpio.PinIn, o *Opts if maxTxSize == 0 { maxTxSize = 4096 // Use a conservative default. } - + // If possible, grab the CS pin. + cs := gpioreg.ByName(cs0Pin) + if cs != nil && cs.Out(csDisabled) != nil { + cs = nil + } d := &Dev{ c: c, maxTxSize: maxTxSize, @@ -95,6 +108,7 @@ func New(p spi.Port, dc gpio.PinOut, reset gpio.PinOut, busy gpio.PinIn, o *Opts model: o.Model, variant: o.DisplayVariant, pcbVariant: o.PCBVariant, + cs: cs, } switch o.Model { @@ -332,7 +346,29 @@ func (d *Dev) reset() (err error) { return } +// setCSPin sets the ChipSelect pin to the desired mode. The Pimoroni driver +// uses manual control over the CS pin. To do this, they require the +// Raspberry Pi /boot/firmware/config.txt to have dtloverlay=spi0-0cs set. +// +// So, if we run with automatic CS handling, we won't be compatible with the +// pimoroni samples. If we run with manual control required, we then require +// the dtoverlay setting. We really don't want to be incompatible with the +// Pimoroni driver because that will confuse people. If the CS Pin is +// not in use, use manual control, and if it is used by the SPI driver, let +// it handle it. +func (d *Dev) setCSPin(mode gpio.Level) error { + if d.cs != nil { + return d.cs.Out(mode) + } + return nil +} + func (d *Dev) sendCommand(command byte, data []byte) (err error) { + d.setCSPin(csEnabled) + if err != nil { + return + } + if err = d.dc.Out(gpio.Low); err != nil { return } @@ -340,6 +376,10 @@ func (d *Dev) sendCommand(command byte, data []byte) (err error) { err = fmt.Errorf("inky: failed to send command %x to inky: %v", command, err) return } + err = d.setCSPin(csDisabled) + if err != nil { + return + } if data != nil { if err = d.sendData(data); err != nil { @@ -351,6 +391,10 @@ func (d *Dev) sendCommand(command byte, data []byte) (err error) { } func (d *Dev) sendData(data []byte) (err error) { + err = d.setCSPin(csEnabled) + if err != nil { + return + } if err = d.dc.Out(gpio.High); err != nil { return err } @@ -367,7 +411,10 @@ func (d *Dev) sendData(data []byte) (err error) { return } } - + err = d.setCSPin(csDisabled) + if err != nil { + return + } return } From 2da607c499e086e068b8a828157fee621db47f21 Mon Sep 17 00:00:00 2001 From: George Sexton Date: Sat, 5 Apr 2025 17:38:48 -0600 Subject: [PATCH 10/14] Fix error --- inky/inky.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inky/inky.go b/inky/inky.go index 9499c70..645254a 100644 --- a/inky/inky.go +++ b/inky/inky.go @@ -364,7 +364,7 @@ func (d *Dev) setCSPin(mode gpio.Level) error { } func (d *Dev) sendCommand(command byte, data []byte) (err error) { - d.setCSPin(csEnabled) + err = d.setCSPin(csEnabled) if err != nil { return } From 3037d5a9b6d9fb8883df2c29a2f84df4d8f61e72 Mon Sep 17 00:00:00 2001 From: George Sexton Date: Sat, 5 Apr 2025 18:02:31 -0600 Subject: [PATCH 11/14] Remove comment --- inky/impression.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/inky/impression.go b/inky/impression.go index b4ae44d..3822b25 100644 --- a/inky/impression.go +++ b/inky/impression.go @@ -156,10 +156,6 @@ func NewImpression(p spi.Port, dc gpio.PinOut, reset gpio.PinOut, busy gpio.PinI if o.Model == IMPRESSION73 { cSpeed = acSpeed } - // The SPI driver has a max buffer size of 4K bytes, but our image size - // is 192K Bytes. To make the Impression 7.3 treat this as single trans- - // action, we have to take over control of the CS pin and manipulate it - // as required. c, err := p.Connect(cSpeed, spi.Mode0, 8) if err != nil { return nil, fmt.Errorf("failed to connect to inky over spi: %v", err) From e455f8e488dc8898f66127f0e5958b24fd902222 Mon Sep 17 00:00:00 2001 From: George Sexton Date: Sat, 5 Apr 2025 22:36:22 -0600 Subject: [PATCH 12/14] remove redundant code --- inky/inky.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/inky/inky.go b/inky/inky.go index 645254a..7b83f0b 100644 --- a/inky/inky.go +++ b/inky/inky.go @@ -412,9 +412,6 @@ func (d *Dev) sendData(data []byte) (err error) { } } err = d.setCSPin(csDisabled) - if err != nil { - return - } return } From 742e8e42405482c78e9c19ef0fa904b096f92f6c Mon Sep 17 00:00:00 2001 From: George Sexton Date: Sat, 12 Apr 2025 17:06:26 -0600 Subject: [PATCH 13/14] Fix palettes. Remove unnecessary memory alloc for pixels. --- inky/impression.go | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/inky/impression.go b/inky/impression.go index 3822b25..70c9046 100644 --- a/inky/impression.go +++ b/inky/impression.go @@ -29,36 +29,36 @@ var _ draw.Image = &DevImpression{} var ( // For more: https://github.com/pimoroni/inky/issues/115#issuecomment-887453065 dsc = []color.NRGBA{ - {0, 0, 0, 0}, // Black + {0, 0, 0, 255}, // Black {255, 255, 255, 255}, // White {0, 255, 0, 255}, // Green {0, 0, 255, 255}, // Blue {255, 0, 0, 255}, // Red {255, 255, 0, 255}, // Yellow {255, 140, 0, 255}, // Orange - {255, 255, 255, 255}, + {255, 255, 255, 0}, // Clear } sc = []color.NRGBA{ - {57, 48, 57, 0}, // Black + {57, 48, 57, 255}, // Black {255, 255, 255, 255}, // White {58, 91, 70, 255}, // Green {61, 59, 94, 255}, // Blue {156, 72, 75, 255}, // Red {208, 190, 71, 255}, // Yellow {177, 106, 73, 255}, // Orange - {255, 255, 255, 255}, + {255, 255, 255, 0}, // Clear } sc7 = []color.NRGBA{ - {0, 0, 0, 0}, // Black + {0, 0, 0, 255}, // Black {217, 242, 255, 255}, // White {3, 124, 76, 255}, // Green {27, 46, 198, 255}, // Blue {245, 80, 34, 255}, // Red {255, 255, 68, 255}, // Yellow {239, 121, 44, 255}, // Orange - {255, 255, 255, 255}, + {255, 255, 255, 0}, // Clear } ) @@ -224,10 +224,10 @@ func NewImpression(p spi.Port, dc gpio.PinOut, reset gpio.PinOut, busy gpio.PinI } // blend recalculates the palette based on the saturation level. -func (d *DevImpression) blend() []color.Color { - sat := float64(d.saturation / 100) +func (d *DevImpression) blend() color.Palette { + sat := float64(d.saturation) / 100.0 - pr := []color.Color{} + pr := make([]color.Color, 0) for i := 0; i < 7; i++ { var rs, gs, bs uint8 if d.Dev.model == IMPRESSION73 { @@ -295,7 +295,7 @@ func (d *DevImpression) Render() error { merged := make([]uint8, len(d.Pix)/2) for i, offset := 0, 0; i < len(d.Pix)-1; i, offset = i+2, offset+1 { - merged[offset] = (d.Pix[i]<<4)&0xF0 | d.Pix[i+1]&0x0F + merged[offset] = ((d.Pix[i] << 4) & 0xF0) | (d.Pix[i+1] & 0x0F) } return d.update(merged) @@ -526,18 +526,16 @@ func (d *DevImpression) updateAC(pix []uint8) error { } // TODO there has to be a better way to force the white colour to be used instead of clear... - buf := make([]byte, len(pix)) for i := range pix { - buf[i] = pix[i] - if buf[i]&0xF == 7 { - buf[i] = (buf[i] & 0xF0) + 1 + if pix[i]&0xF == 7 { + pix[i] = (pix[i] & 0xF0) + 1 } - if buf[i]&0xF0 == 0x70 { - buf[i] = (buf[i] & 0xF) + 0x10 + if pix[i]&0xF0 == 0x70 { + pix[i] = (pix[i] & 0xF) + 0x10 } } - if err := d.sendCommand(ac073TC1DTM, buf); err != nil { + if err := d.sendCommand(ac073TC1DTM, pix); err != nil { return err } @@ -626,6 +624,7 @@ func (d *DevImpression) Draw(r image.Rectangle, src image.Image, sp image.Point) // Dither the image using Floyd–Steinberg dithering algorithm otherwise it won't look as good on the screen. draw.FloydSteinberg.Draw(d, r, src, image.Point{}) + return d.Render() } From b0ebc0dbd418e28dc237936e289728e4f8cdb461 Mon Sep 17 00:00:00 2001 From: George Sexton Date: Sat, 12 Apr 2025 17:20:35 -0600 Subject: [PATCH 14/14] Bump host version to pickup gpioioctl fixes --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 055cda7..fdd2062 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/mattn/go-colorable v0.1.13 golang.org/x/image v0.23.0 periph.io/x/conn/v3 v3.7.2 - periph.io/x/host/v3 v3.8.4 + periph.io/x/host/v3 v3.8.5 ) require ( diff --git a/go.sum b/go.sum index 3b17647..81b42ed 100644 --- a/go.sum +++ b/go.sum @@ -17,5 +17,5 @@ golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= periph.io/x/conn/v3 v3.7.2 h1:qt9dE6XGP5ljbFnCKRJ9OOCoiOyBGlw7JZgoi72zZ1s= periph.io/x/conn/v3 v3.7.2/go.mod h1:Ao0b4sFRo4QOx6c1tROJU1fLJN1hUIYggjOrkIVnpGg= -periph.io/x/host/v3 v3.8.4 h1:QNleTythDd0k6Chu0n+ISrJFlf3LFig9oNbtOIkxoCc= -periph.io/x/host/v3 v3.8.4/go.mod h1:hPq8dISZIc+UNfWoRj+bPH3XEBQqJPdFdx218W92mdc= +periph.io/x/host/v3 v3.8.5 h1:g4g5xE1XZtDiGl1UAJaUur1aT7uNiFLMkyMEiZ7IHII= +periph.io/x/host/v3 v3.8.5/go.mod h1:hPq8dISZIc+UNfWoRj+bPH3XEBQqJPdFdx218W92mdc=