Paperd.Ink Library 0.0.5
Library for interacting with Paperd.Ink devices.
Loading...
Searching...
No Matches
GxEPD2_EPD.cpp
Go to the documentation of this file.
1// Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
2// Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
3//
4// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
5//
6// Author: Jean-Marc Zingg
7//
8// Version: see library.properties
9//
10// Library: https://github.com/ZinggJM/GxEPD2
11
12#include "GxEPD2_EPD.h"
13
14#if defined(ESP8266) || defined(ESP32)
15#include <pgmspace.h>
16#else
17#include <avr/pgmspace.h>
18#endif
19
20GxEPD2_EPD::GxEPD2_EPD(int16_t cs, int16_t dc, int16_t rst, int16_t busy, int16_t busy_level, uint32_t busy_timeout,
21 uint16_t w, uint16_t h, GxEPD2::Panel p, bool c, bool pu, bool fpu) :
22 WIDTH(w), HEIGHT(h), panel(p), hasColor(c), hasPartialUpdate(pu), hasFastPartialUpdate(fpu),
23 _cs(cs), _dc(dc), _rst(rst), _busy(busy), _busy_level(busy_level), _busy_timeout(busy_timeout), _diag_enabled(false),
24 _pSPIx(&SPI), _spi_settings(4000000, MSBFIRST, SPI_MODE0)
25{
26 _initial_write = true;
27 _initial_refresh = true;
28 _power_is_on = false;
29 _using_partial_mode = false;
30 _hibernating = false;
31 _reset_duration = 10;
34}
35
36void GxEPD2_EPD::init(uint32_t serial_diag_bitrate)
37{
38 init(serial_diag_bitrate, true, 10, false);
39}
40
41void GxEPD2_EPD::init(uint32_t serial_diag_bitrate, bool initial, uint16_t reset_duration, bool pulldown_rst_mode)
42{
43 _initial_write = initial;
44 _initial_refresh = initial;
45 _pulldown_rst_mode = pulldown_rst_mode;
46 _power_is_on = false;
47 _using_partial_mode = false;
48 _hibernating = false;
49 _reset_duration = reset_duration;
50 if (serial_diag_bitrate > 0)
51 {
52 Serial.begin(serial_diag_bitrate);
53 _diag_enabled = true;
54 }
55 if (_cs >= 0)
56 {
57 digitalWrite(_cs, HIGH);
58 pinMode(_cs, OUTPUT);
59 }
60 if (_dc >= 0)
61 {
62 digitalWrite(_dc, HIGH);
63 pinMode(_dc, OUTPUT);
64 }
65 _reset();
66 if (_busy >= 0)
67 {
68 pinMode(_busy, INPUT);
69 }
70 _pSPIx->begin();
71 if (_busy == MISO) // may be overridden, to be verified
72 {
73 pinMode(_busy, INPUT);
74 }
75 if (_dc == MISO) // may be overridden, TTGO T5 V2.66
76 {
77 pinMode(_dc, OUTPUT);
78 }
79}
80
81void GxEPD2_EPD::setBusyCallback(void (*busyCallback)(const void*), const void* busy_callback_parameter)
82{
83 _busy_callback = busyCallback;
84 _busy_callback_parameter = busy_callback_parameter;
85}
86
87void GxEPD2_EPD::selectSPI(SPIClass& spi, SPISettings spi_settings)
88{
89 _pSPIx = &spi;
90 _spi_settings = spi_settings;
91}
92
94{
95 if (_rst >= 0)
96 {
98 {
99 digitalWrite(_rst, LOW);
100 pinMode(_rst, OUTPUT);
101 delay(_reset_duration);
102 pinMode(_rst, INPUT_PULLUP);
103 delay(_reset_duration > 10 ? _reset_duration : 10);
104 }
105 else
106 {
107 digitalWrite(_rst, HIGH); // NEEDED for Waveshare "clever" reset circuit, power controller before reset pulse
108 pinMode(_rst, OUTPUT);
109 delay(10); // NEEDED for Waveshare "clever" reset circuit, at least delay(2);
110 digitalWrite(_rst, LOW);
111 delay(_reset_duration);
112 digitalWrite(_rst, HIGH);
113 delay(_reset_duration > 10 ? _reset_duration : 10);
114 }
115 _hibernating = false;
116 }
117}
118
119void GxEPD2_EPD::_waitWhileBusy(const char* comment, uint16_t busy_time)
120{
121 if (_busy >= 0)
122 {
123 delay(1); // add some margin to become active
124 unsigned long start = micros();
125 while (1)
126 {
127 if (digitalRead(_busy) != _busy_level) break;
129 else delay(1);
130 if (digitalRead(_busy) != _busy_level) break;
131 if (micros() - start > _busy_timeout)
132 {
133 Serial.println("Busy Timeout!");
134 break;
135 }
136#if defined(ESP8266) || defined(ESP32)
137 yield(); // avoid wdt
138#endif
139 }
140 if (comment)
141 {
142#if !defined(DISABLE_DIAGNOSTIC_OUTPUT)
143 if (_diag_enabled)
144 {
145 unsigned long elapsed = micros() - start;
146 Serial.print(comment);
147 Serial.print(" : ");
148 Serial.println(elapsed);
149 }
150#endif
151 }
152 (void) start;
153 }
154 else delay(busy_time);
155}
156
158{
159 _pSPIx->beginTransaction(_spi_settings);
160 if (_dc >= 0) digitalWrite(_dc, LOW);
161 if (_cs >= 0) digitalWrite(_cs, LOW);
162 _pSPIx->transfer(c);
163 if (_cs >= 0) digitalWrite(_cs, HIGH);
164 if (_dc >= 0) digitalWrite(_dc, HIGH);
165 _pSPIx->endTransaction();
166}
167
169{
170 _pSPIx->beginTransaction(_spi_settings);
171 if (_cs >= 0) digitalWrite(_cs, LOW);
172 _pSPIx->transfer(d);
173 if (_cs >= 0) digitalWrite(_cs, HIGH);
174 _pSPIx->endTransaction();
175}
176
177void GxEPD2_EPD::_writeData(const uint8_t* data, uint16_t n)
178{
179 _pSPIx->beginTransaction(_spi_settings);
180 if (_cs >= 0) digitalWrite(_cs, LOW);
181 for (uint16_t i = 0; i < n; i++)
182 {
183 _pSPIx->transfer(*data++);
184 }
185 if (_cs >= 0) digitalWrite(_cs, HIGH);
186 _pSPIx->endTransaction();
187}
188
189void GxEPD2_EPD::_writeDataPGM(const uint8_t* data, uint16_t n, int16_t fill_with_zeroes)
190{
191 _pSPIx->beginTransaction(_spi_settings);
192 if (_cs >= 0) digitalWrite(_cs, LOW);
193 for (uint16_t i = 0; i < n; i++)
194 {
195 _pSPIx->transfer(pgm_read_byte(&*data++));
196 }
197 while (fill_with_zeroes > 0)
198 {
199 _pSPIx->transfer(0x00);
200 fill_with_zeroes--;
201 }
202 if (_cs >= 0) digitalWrite(_cs, HIGH);
203 _pSPIx->endTransaction();
204}
205
206void GxEPD2_EPD::_writeDataPGM_sCS(const uint8_t* data, uint16_t n, int16_t fill_with_zeroes)
207{
208 _pSPIx->beginTransaction(_spi_settings);
209 for (uint8_t i = 0; i < n; i++)
210 {
211 if (_cs >= 0) digitalWrite(_cs, LOW);
212 _pSPIx->transfer(pgm_read_byte(&*data++));
213 if (_cs >= 0) digitalWrite(_cs, HIGH);
214 }
215 while (fill_with_zeroes > 0)
216 {
217 if (_cs >= 0) digitalWrite(_cs, LOW);
218 _pSPIx->transfer(0x00);
219 fill_with_zeroes--;
220 if (_cs >= 0) digitalWrite(_cs, HIGH);
221 }
222 _pSPIx->endTransaction();
223}
224
225void GxEPD2_EPD::_writeCommandData(const uint8_t* pCommandData, uint8_t datalen)
226{
227 _pSPIx->beginTransaction(_spi_settings);
228 if (_dc >= 0) digitalWrite(_dc, LOW);
229 if (_cs >= 0) digitalWrite(_cs, LOW);
230 _pSPIx->transfer(*pCommandData++);
231 if (_dc >= 0) digitalWrite(_dc, HIGH);
232 for (uint8_t i = 0; i < datalen - 1; i++) // sub the command
233 {
234 _pSPIx->transfer(*pCommandData++);
235 }
236 if (_cs >= 0) digitalWrite(_cs, HIGH);
237 _pSPIx->endTransaction();
238}
239
240void GxEPD2_EPD::_writeCommandDataPGM(const uint8_t* pCommandData, uint8_t datalen)
241{
242 _pSPIx->beginTransaction(_spi_settings);
243 if (_dc >= 0) digitalWrite(_dc, LOW);
244 if (_cs >= 0) digitalWrite(_cs, LOW);
245 _pSPIx->transfer(pgm_read_byte(&*pCommandData++));
246 if (_dc >= 0) digitalWrite(_dc, HIGH);
247 for (uint8_t i = 0; i < datalen - 1; i++) // sub the command
248 {
249 _pSPIx->transfer(pgm_read_byte(&*pCommandData++));
250 }
251 if (_cs >= 0) digitalWrite(_cs, HIGH);
252 _pSPIx->endTransaction();
253}
254
256{
257 _pSPIx->beginTransaction(_spi_settings);
258 if (_cs >= 0) digitalWrite(_cs, LOW);
259}
260
261void GxEPD2_EPD::_transfer(uint8_t value)
262{
263 _pSPIx->transfer(value);
264}
265
267{
268 if (_cs >= 0) digitalWrite(_cs, HIGH);
269 _pSPIx->endTransaction();
270}
bool _pulldown_rst_mode
Definition GxEPD2_EPD.h:114
bool _diag_enabled
Definition GxEPD2_EPD.h:114
void _endTransfer()
void _writeCommand(uint8_t c)
void _writeData(uint8_t d)
int16_t _busy_level
Definition GxEPD2_EPD.h:112
bool _using_partial_mode
Definition GxEPD2_EPD.h:118
virtual void init(uint32_t serial_diag_bitrate=0)
void _waitWhileBusy(const char *comment=0, uint16_t busy_time=5000)
void(* _busy_callback)(const void *)
Definition GxEPD2_EPD.h:120
bool _power_is_on
Definition GxEPD2_EPD.h:118
bool _initial_refresh
Definition GxEPD2_EPD.h:117
void _startTransfer()
void _writeCommandDataPGM(const uint8_t *pCommandData, uint8_t datalen)
void selectSPI(SPIClass &spi, SPISettings spi_settings)
void _transfer(uint8_t value)
uint16_t _reset_duration
Definition GxEPD2_EPD.h:119
int16_t _dc
Definition GxEPD2_EPD.h:112
GxEPD2_EPD(int16_t cs, int16_t dc, int16_t rst, int16_t busy, int16_t busy_level, uint32_t busy_timeout, uint16_t w, uint16_t h, GxEPD2::Panel p, bool c, bool pu, bool fpu)
void _reset()
void _writeDataPGM_sCS(const uint8_t *data, uint16_t n, int16_t fill_with_zeroes=0)
bool _initial_write
Definition GxEPD2_EPD.h:117
const void * _busy_callback_parameter
Definition GxEPD2_EPD.h:121
uint32_t _busy_timeout
Definition GxEPD2_EPD.h:113
void _writeCommandData(const uint8_t *pCommandData, uint8_t datalen)
int16_t _rst
Definition GxEPD2_EPD.h:112
SPISettings _spi_settings
Definition GxEPD2_EPD.h:116
int16_t _busy
Definition GxEPD2_EPD.h:112
bool _hibernating
Definition GxEPD2_EPD.h:118
void _writeDataPGM(const uint8_t *data, uint16_t n, int16_t fill_with_zeroes=0)
SPIClass * _pSPIx
Definition GxEPD2_EPD.h:115
void setBusyCallback(void(*busyCallback)(const void *), const void *busy_callback_parameter=0)
int16_t _cs
Definition GxEPD2_EPD.h:112
Panel
Definition GxEPD2.h:37