From 2c30718a380dc247b3a249515b7fd1203c2feac2 Mon Sep 17 00:00:00 2001 From: Brian Charous Date: Sun, 15 Jun 2025 17:42:54 -0500 Subject: [PATCH 1/2] add inky impression 7.3 spectra6 support --- inky/impression.go | 182 ++++++++++++++++++++++++++++++++++++++++----- inky/opts.go | 5 +- inky/types.go | 5 +- 3 files changed, 172 insertions(+), 20 deletions(-) diff --git a/inky/impression.go b/inky/impression.go index 70c9046..c64b557 100644 --- a/inky/impression.go +++ b/inky/impression.go @@ -39,6 +39,16 @@ var ( {255, 255, 255, 0}, // Clear } + dsc6 = []color.NRGBA{ + {0, 0, 0, 255}, // Black + {255, 255, 255, 255}, // White + {255, 255, 0, 255}, // Yellow + {255, 0, 0, 255}, // Red + {0, 0, 255, 255}, // Blue + {0, 255, 0, 255}, // Green + {255, 255, 255, 0}, // Clear + } + sc = []color.NRGBA{ {57, 48, 57, 255}, // Black {255, 255, 255, 255}, // White @@ -60,6 +70,16 @@ var ( {239, 121, 44, 255}, // Orange {255, 255, 255, 0}, // Clear } + + sc6 = []color.NRGBA{ + {0, 0, 0, 255}, // Black + {161, 164, 165, 255}, // Gray + {208, 190, 71, 255}, // Yellow + {156, 72, 75, 255}, // Red + {61, 59, 94, 255}, // Blue + {58, 91, 70, 255}, // Green + {255, 255, 255, 0}, // Clear + } ) const ( @@ -129,6 +149,26 @@ const ( ac073TC1CCSET = 0xE0 ac073TC1PWS = 0xE3 ac073TC1TSSET = 0xE6 + + el673PSR = 0x00 + el673PWR = 0x01 + el673POF = 0x02 + el673POFS = 0x03 + el673PON = 0x04 + el673BTST1 = 0x05 + el673BTST2 = 0x06 + el673DSLP = 0x07 + el673BTST3 = 0x08 + el673DTM1 = 0x10 + el673DSP = 0x11 + el673DRF = 0x12 + el673PLL = 0x30 + el673CDI = 0x50 + el673TCON = 0x60 + el673TRES = 0x61 + el673REV = 0x70 + el673VDCS = 0x82 + el673PWS = 0xE3 ) // DevImpression is a handle to an Inky Impression. @@ -206,7 +246,7 @@ func NewImpression(p spi.Port, dc gpio.PinOut, reset gpio.PinOut, busy gpio.PinI d.width = 600 d.height = 448 d.res = 0b11 - case IMPRESSION73: + case IMPRESSION73, IMPRESSION73SPECTRA6: d.width = 800 d.height = 480 d.res = 0b11 @@ -227,28 +267,38 @@ func NewImpression(p spi.Port, dc gpio.PinOut, reset gpio.PinOut, busy gpio.PinI func (d *DevImpression) blend() color.Palette { sat := float64(d.saturation) / 100.0 + var satPalette []color.NRGBA + var dscPalette []color.NRGBA + switch d.Dev.model { + case IMPRESSION73: + satPalette = sc7 + dscPalette = dsc + case IMPRESSION73SPECTRA6: + satPalette = sc6 + dscPalette = dsc6 + default: + satPalette = sc + dscPalette = dsc + } + pr := make([]color.Color, 0) - for i := 0; i < 7; i++ { - var rs, gs, bs uint8 - if d.Dev.model == IMPRESSION73 { - rs, gs, bs = - uint8(float64(sc7[i].R)*sat), - uint8(float64(sc7[i].G)*sat), - uint8(float64(sc7[i].B)*sat) - } else { - rs, gs, bs = - uint8(float64(sc[i].R)*sat), - uint8(float64(sc[i].G)*sat), - uint8(float64(sc[i].B)*sat) - } + for i := range satPalette { + rs, gs, bs := uint8(float64(satPalette[i].R)*sat), + uint8(float64(satPalette[i].G)*sat), + uint8(float64(satPalette[i].B)*sat) rd, gd, bd := - uint8(float64(dsc[i].R)*(1.0-sat)), - uint8(float64(dsc[i].G)*(1.0-sat)), - uint8(float64(dsc[i].B)*(1.0-sat)) + uint8(float64(dscPalette[i].R)*(1.0-sat)), + uint8(float64(dscPalette[i].G)*(1.0-sat)), + uint8(float64(dscPalette[i].B)*(1.0-sat)) + + pr = append(pr, color.RGBA{rs + rd, gs + gd, bs + bd, dscPalette[i].A}) + } - pr = append(pr, color.RGBA{rs + rd, gs + gd, bs + bd, dsc[i].A}) + if d.Dev.model == IMPRESSION73SPECTRA6 { + return pr } + // Add Transparent color and return the result. return append(pr, color.RGBA{255, 255, 255, 0}) } @@ -293,6 +343,14 @@ func (d *DevImpression) Render() error { } } + // remap spectra6 pixels to correct color palette + if d.model == IMPRESSION73SPECTRA6 { + remap := []uint8{0, 1, 2, 3, 5, 6} + for i, pix := range d.Pix { + d.Pix[i] = remap[pix] + } + } + 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) @@ -486,9 +544,68 @@ func (d *DevImpression) resetAC() error { return nil } +func (d *DevImpression) resetEC() error { + // reference code: https://github.com/pimoroni/inky/blob/fef67aab73bb2b6def1eca6003a3f5a3ccec0741/inky/inky_e673.py#L204 + + if err := d.cycleResetGPIO(); err != nil { + return err + } + time.Sleep(30 * time.Millisecond) + if err := d.cycleResetGPIO(); err != nil { + return err + } + time.Sleep(30 * time.Millisecond) + + d.wait(300 * time.Millisecond) + + if err := d.sendCommand(0xAA, []byte{0x49, 0x55, 0x20, 0x08, 0x09, 0x18}); err != nil { + return err + } + if err := d.sendCommand(el673PWR, []byte{0x3F}); err != nil { + return err + } + if err := d.sendCommand(el673PSR, []byte{0x5F, 0x69}); err != nil { + return err + } + if err := d.sendCommand(el673BTST1, []byte{0x40, 0x1F, 0x1F, 0x2C}); err != nil { + return err + } + if err := d.sendCommand(el673BTST3, []byte{0x6F, 0x1F, 0x1F, 0x22}); err != nil { + return err + } + if err := d.sendCommand(el673BTST2, []byte{0x6F, 0x1F, 0x17, 0x17}); err != nil { + return err + } + if err := d.sendCommand(el673POFS, []byte{0x00, 0x54, 0x00, 0x44}); err != nil { + return err + } + if err := d.sendCommand(el673TCON, []byte{0x02, 0x00}); err != nil { + return err + } + if err := d.sendCommand(el673PLL, []byte{0x08}); err != nil { + return err + } + if err := d.sendCommand(el673CDI, []byte{0x3F}); err != nil { + return err + } + if err := d.sendCommand(el673TRES, []byte{0x03, 0x20, 0x01, 0xE0}); err != nil { + return err + } + if err := d.sendCommand(el673PWS, []byte{0x2F}); err != nil { + return err + } + if err := d.sendCommand(el673VDCS, []byte{0x01}); err != nil { + return err + } + + return nil +} + func (d *DevImpression) update(pix []uint8) error { if d.model == IMPRESSION73 { return d.updateAC(pix) + } else if d.model == IMPRESSION73SPECTRA6 { + return d.updateEC(pix) } return d.updateUC(pix) } @@ -557,6 +674,35 @@ func (d *DevImpression) updateAC(pix []uint8) error { return nil } +func (d *DevImpression) updateEC(pix []uint8) error { + if err := d.resetEC(); err != nil { + return err + } + + if err := d.sendCommand(el673DTM1, pix); err != nil { + return err + } + if err := d.sendCommand(el673PON, nil); err != nil { + return err + } + d.wait(300 * time.Millisecond) + + if err := d.sendCommand(el673BTST2, []byte{0x6F, 0x1F, 0x17, 0x49}); err != nil { + return err + } + if err := d.sendCommand(el673DRF, []byte{0x00}); err != nil { + return err + } + d.wait(32 * time.Second) + + if err := d.sendCommand(el673POF, []byte{0x00}); err != nil { + return err + } + d.wait(300 * time.Millisecond) + + return nil +} + // Wait for busy/wait pin. func (d *DevImpression) wait(dur time.Duration) { // Set it as input, with a pull down and enable rising edge triggering. diff --git a/inky/opts.go b/inky/opts.go index 5505188..acc63e2 100644 --- a/inky/opts.go +++ b/inky/opts.go @@ -34,6 +34,7 @@ var ( "Red wHAT (SSD1683)", "Yellow wHAT (SSD1683)", "7-Colour 800x480 (AC073TC1A)", + "Spectra 6 7.3 800 x 480 (E673)", } ) @@ -78,7 +79,7 @@ func DetectOpts(bus i2c.Bus) (*Opts, error) { case 3: options.ModelColor = Yellow options.BorderColor = Yellow - case 4: + case 4, 6: options.ModelColor = Multi options.BorderColor = Color(WhiteImpression) default: @@ -100,6 +101,8 @@ func DetectOpts(bus i2c.Bus) (*Opts, error) { options.Model = IMPRESSION4 case 20: options.Model = IMPRESSION73 + case 22: + options.Model = IMPRESSION73SPECTRA6 default: return nil, fmt.Errorf("failed to get ops: display type %v not supported", data[6]) } diff --git a/inky/types.go b/inky/types.go index 83f4535..31af707 100644 --- a/inky/types.go +++ b/inky/types.go @@ -22,6 +22,7 @@ const ( IMPRESSION4 IMPRESSION57 IMPRESSION73 + IMPRESSION73SPECTRA6 ) // Set sets the Model to a value represented by the string s. Set implements the [flag.Value] interface. @@ -39,8 +40,10 @@ func (m *Model) Set(s string) error { *m = IMPRESSION57 case "IMPRESSION73": *m = IMPRESSION73 + case "IMPRESSION73SPECTRA6": + *m = IMPRESSION73SPECTRA6 default: - return fmt.Errorf("unknown model %q: expected PHAT, PHAT2, WHAT, IMPRESSION4, IMPRESSION57 or IMPRESSION73", s) + return fmt.Errorf("unknown model %q: expected PHAT, PHAT2, WHAT, IMPRESSION4, IMPRESSION57, IMPRESSION73, or IMPRESSION73SPECTRA6", s) } return nil } From b9bf872b419e6123d8555e200064e668ac7f4b3a Mon Sep 17 00:00:00 2001 From: Brian Charous Date: Sun, 15 Jun 2025 19:18:42 -0500 Subject: [PATCH 2/2] run go generate --- inky/types_string.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/inky/types_string.go b/inky/types_string.go index 7c1dab9..96e9de6 100644 --- a/inky/types_string.go +++ b/inky/types_string.go @@ -14,11 +14,12 @@ func _() { _ = x[IMPRESSION4-3] _ = x[IMPRESSION57-4] _ = x[IMPRESSION73-5] + _ = x[IMPRESSION73SPECTRA6-6] } -const _Model_name = "PHATWHATPHAT2IMPRESSION4IMPRESSION57IMPRESSION73" +const _Model_name = "PHATWHATPHAT2IMPRESSION4IMPRESSION57IMPRESSION73IMPRESSION73SPECTRA6" -var _Model_index = [...]uint8{0, 4, 8, 13, 24, 36, 48} +var _Model_index = [...]uint8{0, 4, 8, 13, 24, 36, 48, 68} func (i Model) String() string { if i < 0 || i >= Model(len(_Model_index)-1) {