diff --git a/src/GxEPD2_EPD.cpp b/src/GxEPD2_EPD.cpp index 8df8bef..19b210c 100644 --- a/src/GxEPD2_EPD.cpp +++ b/src/GxEPD2_EPD.cpp @@ -17,11 +17,10 @@ #include #endif -GxEPD2_EPD::GxEPD2_EPD(int16_t cs, int16_t dc, int16_t rst, int16_t busy, int16_t busy_level, uint32_t busy_timeout, +GxEPD2_EPD::GxEPD2_EPD(GxEPD2_HalInterface *hal, int16_t busy_level, uint32_t busy_timeout, uint16_t w, uint16_t h, GxEPD2::Panel p, bool c, bool pu, bool fpu) : WIDTH(w), HEIGHT(h), panel(p), hasColor(c), hasPartialUpdate(pu), hasFastPartialUpdate(fpu), - _cs(cs), _dc(dc), _rst(rst), _busy(busy), _busy_level(busy_level), _busy_timeout(busy_timeout), _diag_enabled(false), - _pSPIx(&SPI), _spi_settings(4000000, MSBFIRST, SPI_MODE0) + _hal(hal), _busy_level(busy_level), _busy_timeout(busy_timeout), _diag_enabled(false) { _initial_write = true; _initial_refresh = true; @@ -54,44 +53,10 @@ void GxEPD2_EPD::init(uint32_t serial_diag_bitrate, bool initial, uint16_t reset Serial.begin(serial_diag_bitrate); _diag_enabled = true; } - if (_cs >= 0) - { - digitalWrite(_cs, HIGH); // preset (less glitch for any analyzer) - pinMode(_cs, OUTPUT); - digitalWrite(_cs, HIGH); // set (needed e.g. for RP2040) - } - if (_dc >= 0) - { - digitalWrite(_dc, HIGH); // preset (less glitch for any analyzer) - pinMode(_dc, OUTPUT); - digitalWrite(_dc, HIGH); // set (needed e.g. for RP2040) - } - _reset(); - if (_busy >= 0) - { - pinMode(_busy, INPUT); - } - _pSPIx->begin(); - if (_busy == MISO) // may be overridden - { - pinMode(_busy, INPUT); - } - if (_dc == MISO) // may be overridden, TTGO T5 V2.66 - { - pinMode(_dc, OUTPUT); - } - if (_cs == MISO) // may be overridden - { - pinMode(_cs, INPUT); - } } void GxEPD2_EPD::end() { - _pSPIx->end(); - if (_cs >= 0) pinMode(_cs, INPUT); - if (_dc >= 0) pinMode(_dc, INPUT); - if (_rst >= 0) pinMode(_rst, INPUT); } void GxEPD2_EPD::setBusyCallback(void (*busyCallback)(const void*), const void* busy_callback_parameter) @@ -100,34 +65,27 @@ void GxEPD2_EPD::setBusyCallback(void (*busyCallback)(const void*), const void* _busy_callback_parameter = busy_callback_parameter; } -void GxEPD2_EPD::selectSPI(SPIClass& spi, SPISettings spi_settings) -{ - _pSPIx = &spi; - _spi_settings = spi_settings; -} - void GxEPD2_EPD::_reset() { - if (_rst >= 0) { if (_pulldown_rst_mode) { - digitalWrite(_rst, LOW); - pinMode(_rst, OUTPUT); - digitalWrite(_rst, LOW); + _hal->rst(LOW); + _hal->rstMode(OUTPUT); + _hal->rst(LOW); delay(_reset_duration); - pinMode(_rst, INPUT_PULLUP); + _hal->rstMode(INPUT_PULLUP); delay(_reset_duration > 10 ? _reset_duration : 10); } else { - digitalWrite(_rst, HIGH); // NEEDED for Waveshare "clever" reset circuit, power controller before reset pulse, preset (less glitch for any analyzer) - pinMode(_rst, OUTPUT); - digitalWrite(_rst, HIGH); // NEEDED for Waveshare "clever" reset circuit, power controller before reset pulse, set (needed e.g. for RP2040) + _hal->rst(HIGH); // NEEDED for Waveshare "clever" reset circuit, power controller before reset pulse, preset (less glitch for any analyzer) + _hal->rstMode(OUTPUT); + _hal->rst(HIGH); // NEEDED for Waveshare "clever" reset circuit, power controller before reset pulse, set (needed e.g. for RP2040) delay(10); // NEEDED for Waveshare "clever" reset circuit, at least delay(2); - digitalWrite(_rst, LOW); + _hal->rst(LOW); delay(_reset_duration); - digitalWrite(_rst, HIGH); + _hal->rst(HIGH); delay(_reset_duration > 10 ? _reset_duration : 10); } _hibernating = false; @@ -136,16 +94,15 @@ void GxEPD2_EPD::_reset() void GxEPD2_EPD::_waitWhileBusy(const char* comment, uint16_t busy_time) { - if (_busy >= 0) { delay(1); // add some margin to become active unsigned long start = micros(); while (1) { - if (digitalRead(_busy) != _busy_level) break; + if (_hal->getBusy() != _busy_level) break; if (_busy_callback) _busy_callback(_busy_callback_parameter); else delay(1); - if (digitalRead(_busy) != _busy_level) break; + if (_hal->getBusy() != _busy_level) break; if (micros() - start > _busy_timeout) { Serial.println("Busy Timeout!"); @@ -169,120 +126,59 @@ void GxEPD2_EPD::_waitWhileBusy(const char* comment, uint16_t busy_time) } (void) start; } - else delay(busy_time); } void GxEPD2_EPD::_writeCommand(uint8_t c) { - _pSPIx->beginTransaction(_spi_settings); - if (_dc >= 0) digitalWrite(_dc, LOW); - if (_cs >= 0) digitalWrite(_cs, LOW); - _pSPIx->transfer(c); - if (_cs >= 0) digitalWrite(_cs, HIGH); - if (_dc >= 0) digitalWrite(_dc, HIGH); - _pSPIx->endTransaction(); + _hal->write(c); } void GxEPD2_EPD::_writeData(uint8_t d) { - _pSPIx->beginTransaction(_spi_settings); - if (_cs >= 0) digitalWrite(_cs, LOW); - _pSPIx->transfer(d); - if (_cs >= 0) digitalWrite(_cs, HIGH); - _pSPIx->endTransaction(); + _hal->write(d); } void GxEPD2_EPD::_writeData(const uint8_t* data, uint16_t n) { - _pSPIx->beginTransaction(_spi_settings); - if (_cs >= 0) digitalWrite(_cs, LOW); - for (uint16_t i = 0; i < n; i++) - { - _pSPIx->transfer(*data++); - } - if (_cs >= 0) digitalWrite(_cs, HIGH); - _pSPIx->endTransaction(); + _hal->write(data, n); } void GxEPD2_EPD::_writeDataPGM(const uint8_t* data, uint16_t n, int16_t fill_with_zeroes) { - _pSPIx->beginTransaction(_spi_settings); - if (_cs >= 0) digitalWrite(_cs, LOW); - for (uint16_t i = 0; i < n; i++) - { - _pSPIx->transfer(pgm_read_byte(&*data++)); - } - while (fill_with_zeroes > 0) - { - _pSPIx->transfer(0x00); - fill_with_zeroes--; - } - if (_cs >= 0) digitalWrite(_cs, HIGH); - _pSPIx->endTransaction(); + _hal->write(data, n, fill_with_zeroes); } void GxEPD2_EPD::_writeDataPGM_sCS(const uint8_t* data, uint16_t n, int16_t fill_with_zeroes) { - _pSPIx->beginTransaction(_spi_settings); - for (uint8_t i = 0; i < n; i++) - { - if (_cs >= 0) digitalWrite(_cs, LOW); - _pSPIx->transfer(pgm_read_byte(&*data++)); - if (_cs >= 0) digitalWrite(_cs, HIGH); - } - while (fill_with_zeroes > 0) - { - if (_cs >= 0) digitalWrite(_cs, LOW); - _pSPIx->transfer(0x00); - fill_with_zeroes--; - if (_cs >= 0) digitalWrite(_cs, HIGH); + _hal->write(data, n); + if (fill_with_zeroes > 0) { + uint8_t buf[fill_with_zeroes]; + memset(buf, 0, fill_with_zeroes); + _hal->write(buf, fill_with_zeroes); } - _pSPIx->endTransaction(); } void GxEPD2_EPD::_writeCommandData(const uint8_t* pCommandData, uint8_t datalen) { - _pSPIx->beginTransaction(_spi_settings); - if (_dc >= 0) digitalWrite(_dc, LOW); - if (_cs >= 0) digitalWrite(_cs, LOW); - _pSPIx->transfer(*pCommandData++); - if (_dc >= 0) digitalWrite(_dc, HIGH); - for (uint8_t i = 0; i < datalen - 1; i++) // sub the command - { - _pSPIx->transfer(*pCommandData++); - } - if (_cs >= 0) digitalWrite(_cs, HIGH); - _pSPIx->endTransaction(); + _hal->writeCmd(pCommandData, datalen, false); } void GxEPD2_EPD::_writeCommandDataPGM(const uint8_t* pCommandData, uint8_t datalen) { - _pSPIx->beginTransaction(_spi_settings); - if (_dc >= 0) digitalWrite(_dc, LOW); - if (_cs >= 0) digitalWrite(_cs, LOW); - _pSPIx->transfer(pgm_read_byte(&*pCommandData++)); - if (_dc >= 0) digitalWrite(_dc, HIGH); - for (uint8_t i = 0; i < datalen - 1; i++) // sub the command - { - _pSPIx->transfer(pgm_read_byte(&*pCommandData++)); - } - if (_cs >= 0) digitalWrite(_cs, HIGH); - _pSPIx->endTransaction(); + _hal->writeCmd(pCommandData, datalen, true); } void GxEPD2_EPD::_startTransfer() { - _pSPIx->beginTransaction(_spi_settings); - if (_cs >= 0) digitalWrite(_cs, LOW); + _hal->startTransfer(); } void GxEPD2_EPD::_transfer(uint8_t value) { - _pSPIx->transfer(value); + _hal->transfer(value); } void GxEPD2_EPD::_endTransfer() { - if (_cs >= 0) digitalWrite(_cs, HIGH); - _pSPIx->endTransaction(); + _hal->endTransfer(); } diff --git a/src/GxEPD2_EPD.h b/src/GxEPD2_EPD.h index 34c1145..1e8ea64 100644 --- a/src/GxEPD2_EPD.h +++ b/src/GxEPD2_EPD.h @@ -13,9 +13,9 @@ #define _GxEPD2_EPD_H_ #include -#include #include +#include #pragma GCC diagnostic ignored "-Wunused-parameter" //#pragma GCC diagnostic ignored "-Wsign-compare" @@ -31,7 +31,7 @@ class GxEPD2_EPD const bool hasPartialUpdate; const bool hasFastPartialUpdate; // constructor - GxEPD2_EPD(int16_t cs, int16_t dc, int16_t rst, int16_t busy, int16_t busy_level, uint32_t busy_timeout, + GxEPD2_EPD(GxEPD2_HalInterface *hal, int16_t busy_level, uint32_t busy_timeout, uint16_t w, uint16_t h, GxEPD2::Panel p, bool c, bool pu, bool fpu); virtual void init(uint32_t serial_diag_bitrate = 0); // serial_diag_bitrate = 0 : disabled virtual void init(uint32_t serial_diag_bitrate, bool initial, uint16_t reset_duration = 10, bool pulldown_rst_mode = false); @@ -97,7 +97,6 @@ class GxEPD2_EPD { return (a > b ? a : b); }; - void selectSPI(SPIClass& spi, SPISettings spi_settings); protected: void _reset(); void _waitWhileBusy(const char* comment = 0, uint16_t busy_time = 5000); @@ -112,16 +111,15 @@ class GxEPD2_EPD void _transfer(uint8_t value); void _endTransfer(); protected: - int16_t _cs, _dc, _rst, _busy, _busy_level; + GxEPD2_HalInterface *_hal; + int16_t _busy_level; uint32_t _busy_timeout; bool _diag_enabled, _pulldown_rst_mode; - SPIClass* _pSPIx; - SPISettings _spi_settings; bool _initial_write, _initial_refresh; bool _power_is_on, _using_partial_mode, _hibernating; bool _init_display_done; uint16_t _reset_duration; - void (*_busy_callback)(const void*); + void (*_busy_callback)(const void*); const void* _busy_callback_parameter; }; diff --git a/src/GxEPD2_Hal.h b/src/GxEPD2_Hal.h new file mode 100644 index 0000000..cb8fb9d --- /dev/null +++ b/src/GxEPD2_Hal.h @@ -0,0 +1,18 @@ +#pragma once + +class GxEPD2_HalInterface { + public: + virtual void rstMode(uint8_t mode) = 0; + virtual void rst(bool level) = 0; + virtual int getBusy(void) = 0; + virtual bool isRst(void) = 0; + + virtual void write(uint8_t buf) = 0; + virtual void write(const uint8_t *buf, uint16_t n) = 0; + virtual void write(const uint8_t *buf, uint16_t n, int16_t fill_with_zeroes) = 0; + virtual void writeCmd(const uint8_t* pCommandData, uint8_t datalen, bool isPGM) = 0; + + virtual void startTransfer(void) = 0; + virtual void endTransfer(void) = 0; + virtual void transfer(const uint8_t val) = 0; +}; diff --git a/src/epd/GxEPD2_150_BN.cpp b/src/epd/GxEPD2_150_BN.cpp index bfb3ddf..dba3d78 100644 --- a/src/epd/GxEPD2_150_BN.cpp +++ b/src/epd/GxEPD2_150_BN.cpp @@ -14,8 +14,8 @@ #include "GxEPD2_150_BN.h" -GxEPD2_150_BN::GxEPD2_150_BN(int16_t cs, int16_t dc, int16_t rst, int16_t busy) : - GxEPD2_EPD(cs, dc, rst, busy, HIGH, 10000000, WIDTH, HEIGHT, panel, hasColor, hasPartialUpdate, hasFastPartialUpdate) +GxEPD2_150_BN::GxEPD2_150_BN(GxEPD2_HalInterface *hal) : + GxEPD2_EPD(hal, HIGH, 10000000, WIDTH, HEIGHT, panel, hasColor, hasPartialUpdate, hasFastPartialUpdate) { } @@ -269,7 +269,7 @@ void GxEPD2_150_BN::refresh(int16_t x, int16_t y, int16_t w, int16_t h) int16_t y1 = y < 0 ? 0 : y; // limit w1 = x1 + w1 < int16_t(WIDTH) ? w1 : int16_t(WIDTH) - x1; // limit h1 = y1 + h1 < int16_t(HEIGHT) ? h1 : int16_t(HEIGHT) - y1; // limit - if ((w1 <= 0) || (h1 <= 0)) return; + if ((w1 <= 0) || (h1 <= 0)) return; // make x1, w1 multiple of 8 w1 += x1 % 8; if (w1 % 8 > 0) w1 += 8 - w1 % 8; @@ -287,7 +287,7 @@ void GxEPD2_150_BN::powerOff() void GxEPD2_150_BN::hibernate() { _PowerOff(); - if (_rst >= 0) + if (_hal->isRst()) { _writeCommand(0x10); // deep sleep mode _writeData(0x1); // enter deep sleep diff --git a/src/epd/GxEPD2_150_BN.h b/src/epd/GxEPD2_150_BN.h index bc46a45..954b9c4 100644 --- a/src/epd/GxEPD2_150_BN.h +++ b/src/epd/GxEPD2_150_BN.h @@ -16,6 +16,7 @@ #define _GxEPD2_150_BN_H_ #include "../GxEPD2_EPD.h" +#include "../GxEPD2_Hal.h" class GxEPD2_150_BN : public GxEPD2_EPD { @@ -33,7 +34,7 @@ class GxEPD2_150_BN : public GxEPD2_EPD static const uint16_t full_refresh_time = 4000; // ms, e.g. 3825000us static const uint16_t partial_refresh_time = 800; // ms, e.g. 736000us // constructor - GxEPD2_150_BN(int16_t cs, int16_t dc, int16_t rst, int16_t busy); + GxEPD2_150_BN(GxEPD2_HalInterface *hal); // methods (virtual) // Support for Bitmaps (Sprites) to Controller Buffer and to Screen void clearScreen(uint8_t value = 0xFF); // init controller memory and screen (default white)