mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-02-18 19:03:16 +00:00
161 lines
5.5 KiB
C++
161 lines
5.5 KiB
C++
// Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
|
|
// Requires HW SPI and Adafruit_GFX. Caution: the e-paper panels require 3.3V supply AND data lines!
|
|
//
|
|
// Display Library based on Demo Example from Good Display: https://www.good-display.com/companyfile/32/
|
|
//
|
|
// Author: Jean-Marc Zingg
|
|
//
|
|
// Version: see library.properties
|
|
//
|
|
// Library: https://github.com/ZinggJM/GxEPD2
|
|
|
|
#include "GxEPD2_EPD.h"
|
|
|
|
#include <Tactility/hal/spi/Spi.h>
|
|
#include <Tactility/kernel/Kernel.h>
|
|
|
|
constexpr auto* TAG = "GxEPD2";
|
|
|
|
GxEPD2_EPD::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) :
|
|
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) {
|
|
_initial_write = true;
|
|
_initial_refresh = true;
|
|
_power_is_on = false;
|
|
_using_partial_mode = false;
|
|
_hibernating = false;
|
|
_init_display_done = false;
|
|
_busy_callback = 0;
|
|
_busy_callback_parameter = 0;
|
|
}
|
|
|
|
void GxEPD2_EPD::init() { init(true, 10, false); }
|
|
|
|
void GxEPD2_EPD::init(bool initial, uint16_t reset_duration, bool pulldown_rst_mode) {
|
|
_initial_write = initial;
|
|
_initial_refresh = initial;
|
|
_pulldown_rst_mode = pulldown_rst_mode;
|
|
_power_is_on = false;
|
|
_using_partial_mode = false;
|
|
_hibernating = false;
|
|
_init_display_done = false;
|
|
}
|
|
|
|
void GxEPD2_EPD::setBusyCallback(void (*busyCallback)(const void*), const void* busy_callback_parameter) {
|
|
_busy_callback = busyCallback;
|
|
_busy_callback_parameter = busy_callback_parameter;
|
|
}
|
|
|
|
void GxEPD2_EPD::_waitWhileBusy(const char* comment, uint16_t busy_time) {
|
|
if (_busy >= 0) {
|
|
tt::kernel::delayMillis(1); // add some margin to become active
|
|
unsigned long start = tt::kernel::getMicros();
|
|
while (1) {
|
|
if (digitalRead(_busy) != _busy_level) break;
|
|
if (_busy_callback) _busy_callback(_busy_callback_parameter);
|
|
else tt::kernel::delayMillis(1);
|
|
if (digitalRead(_busy) != _busy_level) break;
|
|
if (tt::kernel::getMicros() - start > _busy_timeout) {
|
|
TT_LOG_W(TAG, "Busy timeout");
|
|
break;
|
|
}
|
|
vPortYield(); // avoid wdt
|
|
}
|
|
(void)start;
|
|
} else tt::kernel::delayMillis(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();
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
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);
|
|
}
|
|
_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();
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
void GxEPD2_EPD::_startTransfer() {
|
|
_pSPIx->beginTransaction(_spi_settings);
|
|
if (_cs >= 0) digitalWrite(_cs, LOW);
|
|
}
|
|
|
|
void GxEPD2_EPD::_transfer(uint8_t value) { _pSPIx->transfer(value); }
|
|
|
|
void GxEPD2_EPD::_endTransfer() {
|
|
if (_cs >= 0) digitalWrite(_cs, HIGH);
|
|
_pSPIx->endTransaction();
|
|
} |