|  | 
|  | 1 | +package epd7in5v2 | 
|  | 2 | + | 
|  | 3 | +import ( | 
|  | 4 | +	"machine" | 
|  | 5 | +	"time" | 
|  | 6 | +) | 
|  | 7 | + | 
|  | 8 | +// Waveshare 7.5 inch e-ink display v2 | 
|  | 9 | +// https://www.waveshare.com/product/displays/e-paper/epaper-1/7.5inch-e-paper-hat.htm | 
|  | 10 | +// | 
|  | 11 | +// Currently only supporting 2 color display, and full display updates. | 
|  | 12 | +// | 
|  | 13 | +// https://files.waveshare.com/upload/6/60/7.5inch_e-Paper_V2_Specification.pdf | 
|  | 14 | +// https://github.com/waveshareteam/e-Paper/tree/4822c075f5df714f88b02e10c336b4eeff7e603e/Arduino/epd7in5_V2 | 
|  | 15 | + | 
|  | 16 | +const WIDTH int = 800 | 
|  | 17 | +const HEIGHT int = 480 | 
|  | 18 | +const BYTE_WIDTH int = WIDTH / 8 | 
|  | 19 | + | 
|  | 20 | +type EPD7in5_V2 struct { | 
|  | 21 | +	cs  machine.Pin | 
|  | 22 | +	rst machine.Pin | 
|  | 23 | +	dc  machine.Pin | 
|  | 24 | +	bsy machine.Pin | 
|  | 25 | +	pwr machine.Pin | 
|  | 26 | +	bus machine.SPI | 
|  | 27 | +} | 
|  | 28 | + | 
|  | 29 | +func New(cs, rst, dc, bsy, pwr machine.Pin, bus machine.SPI) *EPD7in5_V2 { | 
|  | 30 | +	return &EPD7in5_V2{ | 
|  | 31 | +		cs:  cs, | 
|  | 32 | +		rst: rst, | 
|  | 33 | +		dc:  dc, | 
|  | 34 | +		bsy: bsy, | 
|  | 35 | +		pwr: pwr, | 
|  | 36 | +		bus: bus, | 
|  | 37 | +	} | 
|  | 38 | +} | 
|  | 39 | + | 
|  | 40 | +func (e *EPD7in5_V2) Configure(sck, sdo machine.Pin) error { | 
|  | 41 | +	e.bsy.Configure(machine.PinConfig{Mode: machine.PinInput}) | 
|  | 42 | +	e.cs.Configure(machine.PinConfig{Mode: machine.PinOutput}) | 
|  | 43 | +	e.rst.Configure(machine.PinConfig{Mode: machine.PinOutput}) | 
|  | 44 | +	e.dc.Configure(machine.PinConfig{Mode: machine.PinOutput}) | 
|  | 45 | +	e.pwr.Configure(machine.PinConfig{Mode: machine.PinOutput}) | 
|  | 46 | +	e.pwr.High() | 
|  | 47 | + | 
|  | 48 | +	return e.bus.Configure(machine.SPIConfig{ | 
|  | 49 | +		Frequency: 2_000_000, | 
|  | 50 | +		SCK:       sck, | 
|  | 51 | +		SDO:       sdo, | 
|  | 52 | +		LSBFirst:  false, | 
|  | 53 | +		Mode:      0, | 
|  | 54 | +	}) | 
|  | 55 | +} | 
|  | 56 | + | 
|  | 57 | +func (e *EPD7in5_V2) Command(cmd byte, data []byte) error { | 
|  | 58 | +	e.dc.Low() | 
|  | 59 | +	e.cs.Low() | 
|  | 60 | +	_, err := e.bus.Transfer(cmd) | 
|  | 61 | +	e.cs.High() | 
|  | 62 | + | 
|  | 63 | +	if err != nil || data == nil { | 
|  | 64 | +		return err | 
|  | 65 | +	} | 
|  | 66 | + | 
|  | 67 | +	return e.Data(data) | 
|  | 68 | +} | 
|  | 69 | + | 
|  | 70 | +func (e *EPD7in5_V2) Data(data []byte) error { | 
|  | 71 | +	e.dc.High() | 
|  | 72 | +	e.cs.Low() | 
|  | 73 | +	err := e.bus.Tx(data, []byte{}) | 
|  | 74 | +	e.cs.High() | 
|  | 75 | +	return err | 
|  | 76 | +} | 
|  | 77 | + | 
|  | 78 | +func (e *EPD7in5_V2) waitUntilIdle() error { | 
|  | 79 | +	var err error | 
|  | 80 | +	for { | 
|  | 81 | +		if err = e.Command(0x71, nil); err != nil { | 
|  | 82 | +			return err | 
|  | 83 | +		} | 
|  | 84 | +		if e.bsy.Get() { | 
|  | 85 | +			break | 
|  | 86 | +		} | 
|  | 87 | +		time.Sleep(10 * time.Millisecond) | 
|  | 88 | +	} | 
|  | 89 | +	time.Sleep(20 * time.Millisecond) | 
|  | 90 | +	return nil | 
|  | 91 | +} | 
|  | 92 | + | 
|  | 93 | +func (e *EPD7in5_V2) Reset() { | 
|  | 94 | +	e.rst.High() | 
|  | 95 | +	time.Sleep(20 * time.Millisecond) | 
|  | 96 | +	e.rst.Low() | 
|  | 97 | +	time.Sleep(20 * time.Millisecond) | 
|  | 98 | +	e.rst.High() | 
|  | 99 | +	time.Sleep(20 * time.Millisecond) | 
|  | 100 | +} | 
|  | 101 | + | 
|  | 102 | +func (e *EPD7in5_V2) Init() error { | 
|  | 103 | +	var err error | 
|  | 104 | + | 
|  | 105 | +	// power setting | 
|  | 106 | +	if err = e.Command(0x01, []byte{0x17, 0x17, 0x3F, 0x3F, 0x11}); err != nil { | 
|  | 107 | +		return err | 
|  | 108 | +	} | 
|  | 109 | + | 
|  | 110 | +	// VCOM DC setting | 
|  | 111 | +	if err = e.Command(0x82, []byte{0x24}); err != nil { | 
|  | 112 | +		return err | 
|  | 113 | +	} | 
|  | 114 | + | 
|  | 115 | +	// booster setting | 
|  | 116 | +	if err = e.Command(0x06, []byte{0x27, 0x27, 0x2F, 0x17}); err != nil { | 
|  | 117 | +		return err | 
|  | 118 | +	} | 
|  | 119 | + | 
|  | 120 | +	// OSC setting | 
|  | 121 | +	if err = e.Command(0x30, []byte{0x06}); err != nil { | 
|  | 122 | +		return err | 
|  | 123 | +	} | 
|  | 124 | + | 
|  | 125 | +	// power on | 
|  | 126 | +	if err = e.Command(0x04, nil); err != nil { | 
|  | 127 | +		return err | 
|  | 128 | +	} | 
|  | 129 | +	time.Sleep(100 * time.Millisecond) | 
|  | 130 | +	if err = e.waitUntilIdle(); err != nil { | 
|  | 131 | +		return err | 
|  | 132 | +	} | 
|  | 133 | + | 
|  | 134 | +	// panel setting | 
|  | 135 | +	if err = e.Command(0x00, []byte{0x3F}); err != nil { | 
|  | 136 | +		return err | 
|  | 137 | +	} | 
|  | 138 | + | 
|  | 139 | +	// resolution setting | 
|  | 140 | +	if err = e.Command(0x61, []byte{0x03, 0x20, 0x01, 0xE0}); err != nil { | 
|  | 141 | +		return err | 
|  | 142 | +	} | 
|  | 143 | + | 
|  | 144 | +	// dual SPI mode (off) | 
|  | 145 | +	if err = e.Command(0x15, []byte{0x00}); err != nil { | 
|  | 146 | +		return err | 
|  | 147 | +	} | 
|  | 148 | + | 
|  | 149 | +	// VCOM and data interval | 
|  | 150 | +	if err = e.Command(0x50, []byte{0x10, 0x00}); err != nil { | 
|  | 151 | +		return err | 
|  | 152 | +	} | 
|  | 153 | + | 
|  | 154 | +	// tcon setting | 
|  | 155 | +	if err = e.Command(0x60, []byte{0x22}); err != nil { | 
|  | 156 | +		return err | 
|  | 157 | +	} | 
|  | 158 | + | 
|  | 159 | +	// Gate/Source Start Setting | 
|  | 160 | +	if err = e.Command(0x65, []byte{0x00, 0x00, 0x00, 0x00}); err != nil { | 
|  | 161 | +		return err | 
|  | 162 | +	} | 
|  | 163 | + | 
|  | 164 | +	// Set LUT | 
|  | 165 | +	if err = e.Command(0x20, []byte{ | 
|  | 166 | +		0x00, 0x0F, 0x0F, 0x00, 0x00, 0x01, 0x00, 0x0F, 0x01, 0x0F, 0x01, 0x02, 0x00, 0x0F, | 
|  | 167 | +		0x0F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
|  | 168 | +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
|  | 169 | +	}); err != nil { | 
|  | 170 | +		return err | 
|  | 171 | +	} | 
|  | 172 | + | 
|  | 173 | +	if err = e.Command(0x21, []byte{ | 
|  | 174 | +		0x10, 0x0F, 0x0F, 0x00, 0x00, 0x01, 0x84, 0x0F, 0x01, 0x0F, 0x01, 0x02, 0x20, 0x0F, | 
|  | 175 | +		0x0F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
|  | 176 | +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
|  | 177 | +	}); err != nil { | 
|  | 178 | +		return err | 
|  | 179 | +	} | 
|  | 180 | + | 
|  | 181 | +	if err = e.Command(0x22, []byte{ | 
|  | 182 | +		0x10, 0x0F, 0x0F, 0x00, 0x00, 0x01, 0x84, 0x0F, 0x01, 0x0F, 0x01, 0x02, 0x20, 0x0F, | 
|  | 183 | +		0x0F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
|  | 184 | +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
|  | 185 | +	}); err != nil { | 
|  | 186 | +		return err | 
|  | 187 | +	} | 
|  | 188 | + | 
|  | 189 | +	if err = e.Command(0x23, []byte{ | 
|  | 190 | +		0x80, 0x0F, 0x0F, 0x00, 0x00, 0x01, 0x84, 0x0F, 0x01, 0x0F, 0x01, 0x02, 0x40, 0x0F, | 
|  | 191 | +		0x0F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
|  | 192 | +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
|  | 193 | +	}); err != nil { | 
|  | 194 | +		return err | 
|  | 195 | +	} | 
|  | 196 | + | 
|  | 197 | +	return e.Command(0x24, []byte{ | 
|  | 198 | +		0x80, 0x0F, 0x0F, 0x00, 0x00, 0x01, 0x84, 0x0F, 0x01, 0x0F, 0x01, 0x02, 0x40, 0x0F, | 
|  | 199 | +		0x0F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
|  | 200 | +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
|  | 201 | +	}) | 
|  | 202 | +} | 
|  | 203 | + | 
|  | 204 | +func (e *EPD7in5_V2) Draw(img []byte) error { | 
|  | 205 | +	var err error | 
|  | 206 | +	if err = e.Command(0x13, img); err != nil { | 
|  | 207 | +		return err | 
|  | 208 | +	} | 
|  | 209 | +	if err = e.Command(0x12, nil); err != nil { | 
|  | 210 | +		return err | 
|  | 211 | +	} | 
|  | 212 | +	time.Sleep(100 * time.Millisecond) | 
|  | 213 | +	return e.waitUntilIdle() | 
|  | 214 | +} | 
|  | 215 | + | 
|  | 216 | +func (e *EPD7in5_V2) Clear() error { | 
|  | 217 | +	return e.Draw(make([]byte, BYTE_WIDTH*HEIGHT)) | 
|  | 218 | +} | 
|  | 219 | + | 
|  | 220 | +func (e *EPD7in5_V2) DeepSleep() error { | 
|  | 221 | +	return e.Command(0x07, nil) | 
|  | 222 | +} | 
|  | 223 | + | 
|  | 224 | +func NewImageBuffer() []byte { | 
|  | 225 | +	return make([]byte, BYTE_WIDTH*HEIGHT) | 
|  | 226 | +} | 
0 commit comments