-
Notifications
You must be signed in to change notification settings - Fork 78
/
Inkplate.cpp
358 lines (324 loc) · 9.39 KB
/
Inkplate.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
/**
**************************************************
*
* @file Inkplate.cpp
* @brief Basic funtions for controling inkplate
*
* https://github.com/e-radionicacom/Inkplate-Arduino-library
* For support, please reach over forums: forum.e-radionica.com/en
* For more info about the product, please check: www.inkplate.io
*
* This code is released under the GNU Lesser General Public
*License v3.0: https://www.gnu.org/licenses/lgpl-3.0.en.html Please review the
*LICENSE file included with this example. If you have any questions about
*licensing, please contact techsupport@e-radionica.com Distributed as-is; no
*warranty is given.
*
* @authors @ Soldered
***************************************************/
#include "Inkplate.h"
#if defined(ARDUINO_INKPLATECOLOR) || defined(ARDUINO_INKPLATE2) || defined(ARDUINO_INKPLATE4) || \
defined(ARDUINO_INKPLATE7)
Inkplate::Inkplate() : Adafruit_GFX(E_INK_WIDTH, E_INK_HEIGHT), Graphics(E_INK_WIDTH, E_INK_HEIGHT)
#else
Inkplate::Inkplate(uint8_t _mode) : Adafruit_GFX(E_INK_WIDTH, E_INK_HEIGHT), Graphics(E_INK_WIDTH, E_INK_HEIGHT)
#endif
{
#if !defined(ARDUINO_INKPLATECOLOR) && !defined(ARDUINO_INKPLATE2) && !defined(ARDUINO_INKPLATE4) && \
!defined(ARDUINO_INKPLATE7)
setDisplayMode(_mode);
#endif
}
/**
* @brief clearDisplay function clears memory buffer for display
*
* @note This does not clear the actual display, only the memory buffer, you need to call
* display() function after this to clear the display
*/
void Inkplate::clearDisplay()
{
#if defined(ARDUINO_INKPLATECOLOR)
memset(DMemory4Bit, WHITE << 4 | WHITE, E_INK_WIDTH * E_INK_HEIGHT / 2);
#elif defined(ARDUINO_INKPLATE2)
memset(DMemory4Bit, 0xFF, E_INK_WIDTH * E_INK_HEIGHT / 4);
#elif defined(ARDUINO_INKPLATE4)
memset(DMemory4Bit, 0xFF, (E_INK_WIDTH * E_INK_HEIGHT / 8));
memset(DMemory4Bit + (E_INK_WIDTH * E_INK_HEIGHT / 8), 0x00, (E_INK_WIDTH * E_INK_HEIGHT / 8));
#elif defined(ARDUINO_INKPLATE7)
memset(DMemory4Bit, 0x33, (E_INK_WIDTH * E_INK_HEIGHT / 2));
#else
// Clear 1 bit per pixel display buffer
if (getDisplayMode() == 0)
memset(_partial, 0, E_INK_WIDTH * E_INK_HEIGHT / 8);
// Clear 3 bit per pixel display buffer
if (getDisplayMode() == 1)
memset(DMemory4Bit, 255, E_INK_WIDTH * E_INK_HEIGHT / 2);
#endif
}
#if !defined(ARDUINO_INKPLATECOLOR) && !defined(ARDUINO_INKPLATE2) && !defined(ARDUINO_INKPLATE4) && \
!defined(ARDUINO_INKPLATE7)
/**
* @brief display function update display with new data from buffer
*
* @param bool leaveOn
* if set to 1, it will disable turning supply for eink after
* display update in order to save some time needed for power supply
* to save some time at next display update or increase refreshing speed
*/
void Inkplate::display(bool leaveOn)
{
if (getDisplayMode() == 0)
display1b(leaveOn);
else if (getDisplayMode() == 1)
display3b(leaveOn);
}
/**
* @brief preloadScreen function copy data from partial to data buffer
*/
void Inkplate::preloadScreen()
{
memcpy(DMemoryNew, _partial, E_INK_WIDTH * E_INK_HEIGHT / 8);
}
/**
* @brief einkOn turns on supply for epaper display (TPS65186) [+15 VDC,
* -15VDC, +22VDC, -20VDC, +3.3VDC, VCOM]
*
* @note its important to use this order when turning epaper on.
* using wrong order can irreparably damage epaper
*
* @return 1 if succesfully turned on, 0 if failed
*/
int Inkplate::einkOn()
{
if (getPanelState() == 1)
return 1;
WAKEUP_SET;
delay(5);
#ifdef ARDUINO_INKPLATE6PLUSV2
if (pwrMode != INKPLATE_USB_PWR_ONLY)
{
// Enable all rails
Wire.beginTransmission(0x48);
Wire.write(0x01);
Wire.write(B00100000);
Wire.endTransmission();
}
#else
// Enable all rails
Wire.beginTransmission(0x48);
Wire.write(0x01);
Wire.write(B00100000);
Wire.endTransmission();
#endif
// Modify power up sequence.
Wire.beginTransmission(0x48);
Wire.write(0x09);
Wire.write(B11100100);
Wire.endTransmission();
// Modify power down sequence (VEE and VNEG are swapped)
Wire.beginTransmission(0x48);
Wire.write(0x0b);
Wire.write(B00011011);
Wire.endTransmission();
pinsAsOutputs();
LE_CLEAR;
#if !defined(ARDUINO_ESP32_DEV) && !defined(ARDUINO_INKPLATE6V2) && !defined(ARDUINO_INKPLATE6FLICK)
CL_CLEAR;
#endif
SPH_SET;
GMOD_SET;
SPV_SET;
CKV_CLEAR;
OE_CLEAR;
PWRUP_SET;
setPanelState(1);
unsigned long timer = millis();
do
{
delay(1);
} while ((readPowerGood() != PWR_GOOD_OK) && (millis() - timer) < 250);
if ((millis() - timer) >= 250)
{
einkOff();
return 0;
}
VCOM_SET;
OE_SET;
return 1;
}
/**
* @brief einkOff turns off epaper power supply and put all digital IO
* pins in high Z state
*/
void Inkplate::einkOff()
{
if (getPanelState() == 0)
return;
VCOM_CLEAR;
OE_CLEAR;
GMOD_CLEAR;
#if !defined(ARDUINO_ESP32_DEV) && !defined(ARDUINO_INKPLATE6V2) && !defined(ARDUINO_INKPLATE6FLICK)
GPIO.out &= ~(DATA | LE | CL);
#else
LE_CLEAR;
#endif
CKV_CLEAR;
SPH_CLEAR;
SPV_CLEAR;
PWRUP_CLEAR;
unsigned long timer = millis();
do
{
delay(1);
} while ((readPowerGood() != 0) && (millis() - timer) < 250);
// Do not disable WAKEUP if older Inkplate6Plus is used.
#ifndef ARDUINO_INKPLATE6PLUS
#ifdef ARDUINO_INKPLATE6PLUSV2
if (pwrMode != INKPLATE_USB_PWR_ONLY)
WAKEUP_CLEAR;
#else
WAKEUP_CLEAR; // Disable 3V3 Switch for ePaper.
Wire.beginTransmission(0x48);
Wire.write(0x01);
Wire.write(B00000000);
Wire.endTransmission();
#endif
#endif
pinsZstate();
setPanelState(0);
}
/**
* @brief readPowerGood reads ok status for each rail
*
* @return power good status register
*/
uint8_t Inkplate::readPowerGood()
{
Wire.beginTransmission(0x48);
Wire.write(0x0F);
Wire.endTransmission();
Wire.requestFrom(0x48, 1);
return Wire.read();
}
// LOW LEVEL FUNCTIONS
/**
* @brief vscan_start starts writing new frame and skips first two lines
* that are invisible on screen
*/
void Inkplate::vscan_start()
{
CKV_SET;
delayMicroseconds(7);
SPV_CLEAR;
delayMicroseconds(10);
CKV_CLEAR;
delayMicroseconds(0);
CKV_SET;
delayMicroseconds(8);
SPV_SET;
delayMicroseconds(10);
CKV_CLEAR;
delayMicroseconds(0);
CKV_SET;
delayMicroseconds(18);
CKV_CLEAR;
delayMicroseconds(0);
CKV_SET;
delayMicroseconds(18);
CKV_CLEAR;
delayMicroseconds(0);
CKV_SET;
}
/**
* @brief hscan_start starts writing data into current row
*
* @param uint32_t _d
* data to be written into current row
*/
void Inkplate::hscan_start(uint32_t _d)
{
#if !defined(ARDUINO_ESP32_DEV) && !defined(ARDUINO_INKPLATE6V2)
SPH_CLEAR;
GPIO.out_w1ts = (_d) | CL;
GPIO.out_w1tc = DATA | CL;
SPH_SET;
CKV_SET;
#endif
}
/**
* @brief vscan_end ends current row and prints data to screen
*/
void Inkplate::vscan_end()
{
CKV_CLEAR;
LE_SET;
LE_CLEAR;
delayMicroseconds(0);
}
/**
* @brief pinsZstate sets all tps pins at high z state
*
* @note this is used only when turning off epaper
*/
void Inkplate::pinsZstate()
{
pinMode(2, INPUT);
pinMode(32, INPUT);
pinMode(33, INPUT);
pinModeInternal(IO_INT_ADDR, ioRegsInt, OE, INPUT);
pinModeInternal(IO_INT_ADDR, ioRegsInt, GMOD, INPUT);
pinModeInternal(IO_INT_ADDR, ioRegsInt, SPV, INPUT);
// Set up the EPD Data and CL pins for I2S (only on Inkplate6).
pinMode(0, INPUT);
pinMode(4, INPUT);
pinMode(5, INPUT);
pinMode(18, INPUT);
pinMode(19, INPUT);
pinMode(23, INPUT);
pinMode(25, INPUT);
pinMode(26, INPUT);
pinMode(27, INPUT);
#if defined(ARDUINO_ESP32_DEV) || defined(ARDUINO_INKPLATE6V2) || defined(ARDUINO_INKPLATE5V2) || \
defined(ARDUINO_INKPLATE6FLICK)
// Disable clock for the EPD.
myI2S->conf1.tx_stop_en = 0;
#endif
}
/**
* @brief pinsAsOutputs sets all tps pins as outputs
*/
void Inkplate::pinsAsOutputs()
{
pinMode(2, OUTPUT);
pinMode(32, OUTPUT);
pinMode(33, OUTPUT);
pinModeInternal(IO_INT_ADDR, ioRegsInt, OE, OUTPUT);
pinModeInternal(IO_INT_ADDR, ioRegsInt, GMOD, OUTPUT);
pinModeInternal(IO_INT_ADDR, ioRegsInt, SPV, OUTPUT);
#if defined(ARDUINO_ESP32_DEV) || defined(ARDUINO_INKPLATE6V2) || defined(ARDUINO_INKPLATE5V2) || \
defined(ARDUINO_INKPLATE6FLICK)
// Set up the EPD Data and CL pins for I2S.
setI2S1pin(0, I2S1O_BCK_OUT_IDX, 0);
setI2S1pin(4, I2S1O_DATA_OUT0_IDX, 0);
setI2S1pin(5, I2S1O_DATA_OUT1_IDX, 0);
setI2S1pin(18, I2S1O_DATA_OUT2_IDX, 0);
setI2S1pin(19, I2S1O_DATA_OUT3_IDX, 0);
setI2S1pin(23, I2S1O_DATA_OUT4_IDX, 0);
setI2S1pin(25, I2S1O_DATA_OUT5_IDX, 0);
setI2S1pin(26, I2S1O_DATA_OUT6_IDX, 0);
setI2S1pin(27, I2S1O_DATA_OUT7_IDX, 0);
// Start sending clock to the EPD.
myI2S->conf1.tx_stop_en = 1;
#else
pinMode(0, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(18, OUTPUT);
pinMode(19, OUTPUT);
pinMode(23, OUTPUT);
pinMode(25, OUTPUT);
pinMode(26, OUTPUT);
pinMode(27, OUTPUT);
#endif
}
#endif