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 }