diff --git a/inky/inky.go b/inky/inky.go index 86960f0..edcdb03 100644 --- a/inky/inky.go +++ b/inky/inky.go @@ -9,6 +9,9 @@ import ( "fmt" "image" "image/color" + "periph.io/x/conn/v3/gpio/gpioreg" + "periph.io/x/conn/v3/i2c/i2creg" + "periph.io/x/conn/v3/spi/spireg" "time" "periph.io/x/conn/v3" @@ -111,6 +114,44 @@ type Opts struct { BorderColor Color } +// DetectOpts tries to read the device opts from EEPROM, it is recommended to use I2C bus "1" +func DetectOpts(i2cBus string) (*Opts, error) { + // Read data from EEPROM + data, err := readEep(i2cBus) + if err != nil { + return nil, fmt.Errorf("failed to detect Inky board: %v", err) + } + + options := new(Opts) + + switch data[6] { + case 1, 4, 5: + options.Model = PHAT + case 10, 11, 12: + options.Model = PHAT2 + case 2, 3, 6, 7, 8: + options.Model = WHAT + default: + return nil, fmt.Errorf("failed to get ops: display type not supported") + } + + switch data[4] { + case 1: + options.ModelColor = Black + options.BorderColor = Black + case 2: + options.ModelColor = Red + options.BorderColor = Red + case 3: + options.ModelColor = Yellow + options.BorderColor = Yellow + default: + return nil, fmt.Errorf("failed to get ops: color not supported") + } + + return options, nil +} + var borderColor = map[Color]byte{ Black: 0x00, Red: 0x73, @@ -163,6 +204,25 @@ func New(p spi.Port, dc gpio.PinOut, reset gpio.PinOut, busy gpio.PinIn, o *Opts return d, nil } +// NewDetected tries to open a handle to an Inky pHat or wHAT automatically detected from EEPROM +func NewDetected() (*Dev, error) { + opts, err := DetectOpts("1") + if err != nil { + return nil, err + } + + spiPort, err := spireg.Open("SPI0.0") + if err != nil { + return nil, err + } + + dcPin := gpioreg.ByName("22") + resetPin := gpioreg.ByName("27") + busyPin := gpioreg.ByName("17") + + return New(spiPort, dcPin, resetPin, busyPin, opts) +} + // Dev is a handle to an Inky. type Dev struct { c conn.Conn @@ -428,5 +488,24 @@ func pack(bits []bool) ([]byte, error) { return ret, nil } +func readEep(i2cBus string) ([]byte, error) { + bus, err := i2creg.Open(i2cBus) + if err != nil { + return nil, err + } + defer bus.Close() + + // Inky uses SMBus, specify read registry with data + write := []byte{0x00, 0x00} + + data := make([]byte, 29) + + if err := bus.Tx(0x50, write, data); err != nil { + return nil, err + } + + return data, nil +} + var _ display.Drawer = &Dev{} var _ conn.Resource = &Dev{}