diff --git a/lib/LOLIN_EPD/src/LOLIN_EPD.h b/lib/LOLIN_EPD/src/LOLIN_EPD.h index dacd000716..2af5b96351 100644 --- a/lib/LOLIN_EPD/src/LOLIN_EPD.h +++ b/lib/LOLIN_EPD/src/LOLIN_EPD.h @@ -117,5 +117,7 @@ class LOLIN_EPD: public Adafruit_GFX #include "LOLIN_UC8151D.h" #include "LOLIN_SSD1680.h" #include "Waveshare_2in7.h" +#include "Waveshare_1in54bv2.h" +#include "MH_ET_Live_1in54.h" #endif diff --git a/lib/LOLIN_EPD/src/MH_ET_Live_1in54.cpp b/lib/LOLIN_EPD/src/MH_ET_Live_1in54.cpp new file mode 100644 index 0000000000..9e94c249f8 --- /dev/null +++ b/lib/LOLIN_EPD/src/MH_ET_Live_1in54.cpp @@ -0,0 +1,333 @@ +#include "LOLIN_EPD.h" +#include "MH_ET_Live_1in54.h" + +/////////////////////////////////////////////////// +const unsigned char MH_ET_Live_lut_full_update[] PROGMEM = +{ + 0x02, 0x02, 0x01, 0x11, 0x12, 0x12, 0x22, 0x22, + 0x66, 0x69, 0x69, 0x59, 0x58, 0x99, 0x99, 0x88, + 0x00, 0x00, 0x00, 0x00, 0xF8, 0xB4, 0x13, 0x51, + 0x35, 0x51, 0x51, 0x19, 0x01, 0x00 +}; + + +/////////////////EPD settings Functions///////////////////// + + +#define BUSY_WAIT 1000 // msec + +/*! + @brief constructor if using on-chip RAM and hardware SPI + @param width the width of the display in pixels + @param height the height of the display in pixels + @param DC the data/command pin to use + @param RST the reset pin to use + @param CS the chip select pin to use + @param BUSY the busy pin to use + */ + +MH_ET_Live_1in54::MH_ET_Live_1in54(int width, int height, int8_t DC, int8_t RST, int8_t CS, int8_t BUSY) + : LOLIN_EPD(width, height, DC, RST, CS, BUSY), _width(width), _height(height) { + if ((_height % 8) > 0) { + _height_8bit = (_height / 8 + 1) * 8; + } else { + _height_8bit = _height; + } + + bw_bufsize = _width * _height_8bit / 8; + bw_buf = (uint8_t *)malloc(bw_bufsize); + red_buf = (uint8_t *)malloc(bw_bufsize); + red_bufsize = bw_bufsize; +} + +/**************************************************************************/ + +/*! + @brief begin communication with and set up the display. + @param reset if true the reset pin will be toggled. + */ + +/**************************************************************************/ +void MH_ET_Live_1in54::begin(bool reset) { + LOLIN_EPD::begin(reset); + + sendCmd(MH_ET_DRIVER_OUTPUT_CONTROL); + sendData((_height - 1)); + sendData((_height - 1) >> 8); + sendData(0x00); + sendCmd(MH_ET_BOOSTER_SOFT_START_CONTROL); + sendData(0xD7); + sendData(0xD6); + sendData(0x9D); + sendCmd(MH_ET_WRITE_VCOM_REGISTER); + sendData(0xA8); + sendCmd(MH_ET_SET_DUMMY_LINE_PERIOD); + sendData(0x1A); + sendCmd(MH_ET_SET_GATE_LINE_WIDTH); + sendData(0x08); + sendCmd(MH_ET_DATA_ENTRY_MODE_SETTING); + sendData(0x03); + setLut(MH_ET_Live_lut_full_update); + + /* EPD hardware init end */ + readBusy(); +} + +/** + * @brief: set the look-up table register + */ +void MH_ET_Live_1in54::setLut(const unsigned char *lut) +{ + sendCmd(MH_ET_WRITE_LUT_REGISTER); + + /* the length of look-up table is 30 bytes */ + for (int i = 0; i < 30; i++) { + sendData(pgm_read_byte(&(lut[i]))); + } +} + +void MH_ET_Live_1in54::display() { + sendCmd(MH_ET_WRITE_RAM); // write RAM for black(0)/white (1) + delay(2); + + for (uint16_t i = 0; i < bw_bufsize; i++) { + sendData(bw_buf[i]); + } + delay(2); + + sendCmd(MH_ET_WRITE_RAM_RED); // write RAM for red(1)/white (0) + + for (uint16_t i = 0; i < red_bufsize; i++) { + sendData(red_buf[i]); + } + delay(2); + + + update(); +} + +void MH_ET_Live_1in54::update() { + sendCmd(MH_ET_DISPLAY_UPDATE_CONTROL_2); + sendData(0xF7); + sendCmd(MH_ET_MASTER_ACTIVATION); + readBusy(); +} + +/**************************************************************************/ + +/*! + @brief draw a single pixel on the screen + @param x the x axis position + @param y the y axis position + @param color the color of the pixel + */ + +/**************************************************************************/ +void MH_ET_Live_1in54::drawPixel(int16_t x, int16_t y, uint16_t color) { + uint8_t *pBuf; + + // Transformed to native pixels + if ((x < 0) || (x >= width()) || (y < 0) || (y >= height())) { + return; + } + + // check rotation, move pixel around if necessary + switch (getRotation()) { + case 0: + EPD_swap(x, y); + y = WIDTH - y - 1; + break; + case 1: + break; + case 2: + EPD_swap(x, y); + x = HEIGHT - x - 1; + break; + case 3: + x = HEIGHT - x - 1; + y = WIDTH - y - 1; + break; + } + + // make our buffer happy + x = (x == 0 ? 1 : x); + + uint16_t addr = (x + _height_8bit * y) / 8; + + if (color == EPD_RED) { + pBuf = red_buf + addr; + } else { + pBuf = bw_buf + addr; + } + + // x is which column + switch (color) { + case EPD_WHITE: + *pBuf |= (0x80 >> (x % 8)); // (1 << (7 - y % 8)); + break; + case EPD_RED: + case EPD_BLACK: + *pBuf &= ~(0x80 >> (x % 8)); // ~(1 << (7 - y % 8)); + break; + case EPD_INVERSE: + *pBuf ^= (0x80 >> (x % 8)); // (1 << (7 - y % 8)); + break; + } +} + +/**************************************************************************/ + +/*! + @brief clear all data buffers + */ + +/**************************************************************************/ +void MH_ET_Live_1in54::clearBuffer() { + memset(bw_buf, 0xFF, bw_bufsize); + memset(red_buf, 0x00, red_bufsize); +} + +/**************************************************************************/ + +/*! + @brief clear the display twice to remove any spooky ghost images + */ + +/**************************************************************************/ +void MH_ET_Live_1in54::clearDisplay() { + clearBuffer(); + display(); + + // delay(100); + update(); +} + +void MH_ET_Live_1in54::readBusy() { + if (busy >= 0) { + while (1) { + if (digitalRead(busy) == 0) { + delay(1); + break; + } + delay(0); + } + } else { + delay(BUSY_WAIT); + } +} + +// void MH_ET_Live_1in54::selectLUT(uint8_t *wave_data) { +// uint8_t count; + +// sendCmd(0x32); + +// for (count = 0; count < 70; count++) { +// sendData(pgm_read_byte(&wave_data[count])); +// } +// } + +void MH_ET_Live_1in54::deepSleep() { + sendCmd(EPD1IN54B_DEEP_SLEEP); + sendData(0xa5); +} + +void MH_ET_Live_1in54::partInit() +{ + // partBaseImg(); + + // sendCmd(0x2C); //VCOM Voltage + // sendData(0x26); + + // readBusy(); + // selectLUT((unsigned char *)LUT_DATA_part); + // sendCmd(0x37); + // sendData(0x00); + // sendData(0x00); + // sendData(0x00); + // sendData(0x00); + // sendData(0x40); + // sendData(0x00); + // sendData(0x00); + + // sendCmd(0x22); + // sendData(0xC0); + // sendCmd(0x20); + // readBusy(); + + // sendCmd(0x3C); //BorderWavefrom + // sendData(0x01); +} + +void MH_ET_Live_1in54::partBaseImg() +{ + // sendCmd(0x24); ////Write Black and White image to RAM + + // for (uint16_t i = 0; i < bw_bufsize; i++) { + // sendData(bw_buf[i]); + // } + + // sendCmd(0x26); ////Write Black and White image to RAM + + // for (uint16_t i = 0; i < bw_bufsize; i++) { + // sendData(bw_buf[i]); + // } + + // update(); +} + +void MH_ET_Live_1in54::partUpdate() +{ + // sendCmd(0x22); + // sendData(0x0C); + // sendCmd(0x20); + // readBusy(); +} + +void MH_ET_Live_1in54::partDisplay(int16_t x_start, int16_t y_start, const unsigned char *datas, int16_t PART_COLUMN, int16_t PART_LINE) +{ + // int16_t i; + // int16_t x_end, y_start1, y_start2, y_end1, y_end2; + + // x_start = x_start / 8; // + // x_end = x_start + PART_LINE / 8 - 1; + + // y_start1 = 0; + // y_start2 = y_start; + + // if (y_start >= 256) + // { + // y_start1 = y_start2 / 256; + // y_start2 = y_start2 % 256; + // } + // y_end1 = 0; + // y_end2 = y_start + PART_COLUMN - 1; + + // if (y_end2 >= 256) + // { + // y_end1 = y_end2 / 256; + // y_end2 = y_end2 % 256; + // } + + // sendCmd(0x44); // set RAM x address start/end, in page 35 + // sendData(x_start); // RAM x address start at 00h; + // sendData(x_end); // RAM x address end at 0fh(15+1)*8->128 + // sendCmd(0x45); // set RAM y address start/end, in page 35 + // sendData(y_start2); // RAM y address start at 0127h; + // sendData(y_start1); // RAM y address start at 0127h; + // sendData(y_end2); // RAM y address end at 00h; + // sendData(y_end1); // ????=0 + + // sendCmd(0x4E); // set RAM x address count to 0; + // sendData(x_start); + // sendCmd(0x4F); // set RAM y address count to 0X127; + // sendData(y_start2); + // sendData(y_start1); + + // sendCmd(0x24); // Write Black and White image to RAM + + // for (i = 0; i < PART_COLUMN * PART_LINE / 8; i++) + // { + // sendData(pgm_read_byte(&datas[i])); + // } + // partUpdate(); +} diff --git a/lib/LOLIN_EPD/src/MH_ET_Live_1in54.h b/lib/LOLIN_EPD/src/MH_ET_Live_1in54.h new file mode 100644 index 0000000000..02c71cf1a3 --- /dev/null +++ b/lib/LOLIN_EPD/src/MH_ET_Live_1in54.h @@ -0,0 +1,120 @@ +#ifndef __MH_ET_LIVE_1in54_H +#define __MH_ET_LIVE_1in54_H + +#ifdef __AVR__ + # include +#elif defined(ESP8266) || defined(ESP32) + # include +#else // ifdef __AVR__ + # define pgm_read_byte(addr) (*(const unsigned char *)(addr)) ///< read bytes from program memory +#endif // ifdef __AVR__ + +#include "LOLIN_EPD.h" + +// EPD1IN54B commands +// #define EPD1IN54B_PANEL_SETTING 0x00 +// #define EPD1IN54B_POWER_SETTING 0x01 +// #define EPD1IN54B_POWER_OFF 0x02 +// #define EPD1IN54B_POWER_OFF_SEQUENCE_SETTING 0x03 +// #define EPD1IN54B_POWER_ON 0x04 +// #define EPD1IN54B_POWER_ON_MEASURE 0x05 +// #define EPD1IN54B_BOOSTER_SOFT_START 0x06 +// #define EPD1IN54B_DEEP_SLEEP 0x07 +// #define EPD1IN54B_DATA_START_TRANSMISSION_1 0x10 +// #define EPD1IN54B_DATA_STOP 0x11 +// #define EPD1IN54B_DISPLAY_REFRESH 0x12 +// #define EPD1IN54B_DATA_START_TRANSMISSION_2 0x13 +// #define EPD1IN54B_PLL_CONTROL 0x30 +// #define EPD1IN54B_TEMPERATURE_SENSOR_COMMAND 0x40 +// #define EPD1IN54B_TEMPERATURE_SENSOR_CALIBRATION 0x41 +// #define EPD1IN54B_TEMPERATURE_SENSOR_WRITE 0x42 +// #define EPD1IN54B_TEMPERATURE_SENSOR_READ 0x43 +// #define EPD1IN54B_VCOM_AND_DATA_INTERVAL_SETTING 0x50 +// #define EPD1IN54B_LOW_POWER_DETECTION 0x51 +// #define EPD1IN54B_TCON_SETTING 0x60 +// #define EPD1IN54B_TCON_RESOLUTION 0x61 +// #define EPD1IN54B_SOURCE_AND_GATE_START_SETTING 0x62 +// #define EPD1IN54B_GET_STATUS 0x71 +// #define EPD1IN54B_AUTO_MEASURE_VCOM 0x80 +// #define EPD1IN54B_VCOM_VALUE 0x81 +// #define EPD1IN54B_VCM_DC_SETTING_REGISTER 0x82 +// #define EPD1IN54B_PROGRAM_MODE 0xA0 +// #define EPD1IN54B_ACTIVE_PROGRAM 0xA1 +// #define EPD1IN54B_READ_OTP_DATA 0xA2 +// MH-ET Live EPD 1.54 Inch commands +#define MH_ET_DRIVER_OUTPUT_CONTROL 0x01 +#define MH_ET_BOOSTER_SOFT_START_CONTROL 0x0C +#define MH_ET_GATE_SCAN_START_POSITION 0x0F +#define MH_ET_DEEP_SLEEP_MODE 0x10 +#define MH_ET_DATA_ENTRY_MODE_SETTING 0x11 +#define MH_ET_SW_RESET 0x12 +#define MH_ET_TEMPERATURE_SENSOR_CONTROL 0x1A +#define MH_ET_MASTER_ACTIVATION 0x20 +#define MH_ET_DISPLAY_UPDATE_CONTROL_1 0x21 +#define MH_ET_DISPLAY_UPDATE_CONTROL_2 0x22 +#define MH_ET_WRITE_RAM 0x24 +#define MH_ET_WRITE_RAM_RED 0x26 +#define MH_ET_WRITE_VCOM_REGISTER 0x2C +#define MH_ET_WRITE_LUT_REGISTER 0x32 +#define MH_ET_SET_DUMMY_LINE_PERIOD 0x3A +#define MH_ET_SET_GATE_LINE_WIDTH 0x3B +#define MH_ET_BORDER_WAVEFORM_CONTROL 0x3C +#define MH_ET_SET_RAM_X_ADDRESS_START_END_POSITION 0x44 +#define MH_ET_SET_RAM_Y_ADDRESS_START_END_POSITION 0x45 +#define MH_ET_SET_RAM_X_ADDRESS_COUNTER 0x4E +#define MH_ET_SET_RAM_Y_ADDRESS_COUNTER 0x4F +#define MH_ET_NOP 0xFF + +/**************************************************************************/ + +/*! + @brief Class for interfacing with MH-ET Live 1.54" 200x200 drivers + */ + +/**************************************************************************/ +class MH_ET_Live_1in54 : public LOLIN_EPD { +public: + + MH_ET_Live_1in54(int width, + int height, + int8_t DC, + int8_t RST, + int8_t CS, + int8_t BUSY = -1); + + void begin(bool reset = true); + + void drawPixel(int16_t x, + int16_t y, + uint16_t color); + + void display(); + void update(); + + void clearBuffer(); + void clearDisplay(); + + void deepSleep(); + + void partBaseImg(); + void partInit(); + void partDisplay(int16_t x_start, + int16_t y_start, + const unsigned char *datas, + int16_t PART_COLUMN, + int16_t PART_LINE); + void partUpdate(); + +protected: + + void readBusy(); + int _height_8bit; // height 8-bit alignment + +private: + + int _width; + int _height; + void setLut(const unsigned char *lut); +}; + +#endif // ifndef __MH_ET_LIVE_1in54_H diff --git a/lib/LOLIN_EPD/src/Waveshare_1in54bv2.cpp b/lib/LOLIN_EPD/src/Waveshare_1in54bv2.cpp new file mode 100644 index 0000000000..7699e65e0e --- /dev/null +++ b/lib/LOLIN_EPD/src/Waveshare_1in54bv2.cpp @@ -0,0 +1,329 @@ +#include "LOLIN_EPD.h" +#include "Waveshare_1in54bv2.h" + +/////////////////////////////////////////////////// + + +/////////////////EPD settings Functions///////////////////// + + +#define BUSY_WAIT 1000 // msec + +/*! + @brief constructor if using on-chip RAM and hardware SPI + @param width the width of the display in pixels + @param height the height of the display in pixels + @param DC the data/command pin to use + @param RST the reset pin to use + @param CS the chip select pin to use + @param BUSY the busy pin to use + */ + +Waveshare_1in54b::Waveshare_1in54b(int width, int height, int8_t DC, int8_t RST, int8_t CS, int8_t BUSY) + : LOLIN_EPD(width, height, DC, RST, CS, BUSY) { + if ((height % 8) > 0) { + _height_8bit = (height / 8 + 1) * 8; + } else { + _height_8bit = height; + } + + bw_bufsize = width * _height_8bit / 8; + bw_buf = (uint8_t *)malloc(bw_bufsize); + red_buf = (uint8_t *)malloc(bw_bufsize); + red_bufsize = bw_bufsize; +} + +/**************************************************************************/ + +/*! + @brief begin communication with and set up the display. + @param reset if true the reset pin will be toggled. + */ + +/**************************************************************************/ +void Waveshare_1in54b::begin(bool reset) { + LOLIN_EPD::begin(reset); + + readBusy(); + sendCmd(0x12); + readBusy(); + + sendCmd(EPD1IN54B_POWER_SETTING); // Driver output control + sendData(0xC7); + sendData(0x00); + sendData(0x01); + + sendCmd(EPD1IN54B_DATA_STOP); // data entry mode + sendData(0x01); + + sendCmd(0x44); // set Ram-X address start/end position + sendData(0x00); + sendData(0x18); // 0x18-->(24+1)*8=200 + + sendCmd(0x45); // set Ram-Y address start/end position + sendData(0xC7); // 0xC7-->(199+1)=200 + sendData(0x00); + sendData(0x00); + sendData(0x00); + + sendCmd(0x3C); // BorderWavefrom + sendData(0x05); + + sendCmd(0x18); // Read built-in temperature sensor + sendData(0x80); + + sendCmd(0x4E); // set RAM x address count to 0; + sendData(0x00); + sendCmd(0x4F); // set RAM y address count to 0X199; + sendData(0xC7); + sendData(0x00); + + /* EPD hardware init end */ + readBusy(); +} + +void Waveshare_1in54b::display() { + sendCmd(0x24); // write RAM for black(0)/white (1) + delay(2); + + for (uint16_t i = 0; i < bw_bufsize; i++) { + sendData(bw_buf[i]); + } + delay(2); + + sendCmd(0x26); // write RAM for red(1)/white (0) + + for (uint16_t i = 0; i < red_bufsize; i++) { + sendData(red_buf[i]); + } + delay(2); + + + update(); +} + +void Waveshare_1in54b::update() { + sendCmd(0x22); + sendData(0xF7); + sendCmd(0x20); + readBusy(); +} + +/**************************************************************************/ + +/*! + @brief draw a single pixel on the screen + @param x the x axis position + @param y the y axis position + @param color the color of the pixel + */ + +/**************************************************************************/ +void Waveshare_1in54b::drawPixel(int16_t x, int16_t y, uint16_t color) { + uint8_t *pBuf; + + // Transformed to native pixels + if ((x < 0) || (x >= width()) || (y < 0) || (y >= height())) { + return; + } + + // check rotation, move pixel around if necessary + switch (getRotation()) { + case 0: + EPD_swap(x, y); + y = WIDTH - y - 1; + break; + case 1: + break; + case 2: + EPD_swap(x, y); + x = HEIGHT - x - 1; + break; + case 3: + x = HEIGHT - x - 1; + y = WIDTH - y - 1; + break; + } + + // make our buffer happy + x = (x == 0 ? 1 : x); + + uint16_t addr = (x + _height_8bit * y) / 8; + + if (color == EPD_RED) { + pBuf = red_buf + addr; + } else { + pBuf = bw_buf + addr; + } + + // x is which column + switch (color) { + case EPD_WHITE: + *pBuf |= (0x80 >> (x % 8)); // (1 << (7 - y % 8)); + break; + case EPD_RED: + case EPD_BLACK: + *pBuf &= ~(0x80 >> (x % 8)); // ~(1 << (7 - y % 8)); + break; + case EPD_INVERSE: + *pBuf ^= (0x80 >> (x % 8)); // (1 << (7 - y % 8)); + break; + } +} + +/**************************************************************************/ + +/*! + @brief clear all data buffers + */ + +/**************************************************************************/ +void Waveshare_1in54b::clearBuffer() { + memset(bw_buf, 0xFF, bw_bufsize); + memset(red_buf, 0x00, red_bufsize); +} + +/**************************************************************************/ + +/*! + @brief clear the display twice to remove any spooky ghost images + */ + +/**************************************************************************/ +void Waveshare_1in54b::clearDisplay() { + clearBuffer(); + display(); + + // delay(100); + update(); +} + +void Waveshare_1in54b::readBusy() { + if (busy >= 0) { + while (1) { + if (digitalRead(busy) == 0) { + delay(1); + break; + } + delay(0); + } + } else { + delay(BUSY_WAIT); + } +} + +// void Waveshare_1in54b::selectLUT(uint8_t *wave_data) { +// uint8_t count; + +// sendCmd(0x32); + +// for (count = 0; count < 70; count++) { +// sendData(pgm_read_byte(&wave_data[count])); +// } +// } + +void Waveshare_1in54b::deepSleep() { + sendCmd(EPD1IN54B_DEEP_SLEEP); + sendData(0xa5); +} + +void Waveshare_1in54b::partInit() +{ + // partBaseImg(); + + // sendCmd(0x2C); //VCOM Voltage + // sendData(0x26); + + // readBusy(); + // selectLUT((unsigned char *)LUT_DATA_part); + // sendCmd(0x37); + // sendData(0x00); + // sendData(0x00); + // sendData(0x00); + // sendData(0x00); + // sendData(0x40); + // sendData(0x00); + // sendData(0x00); + + // sendCmd(0x22); + // sendData(0xC0); + // sendCmd(0x20); + // readBusy(); + + // sendCmd(0x3C); //BorderWavefrom + // sendData(0x01); +} + +void Waveshare_1in54b::partBaseImg() +{ + // sendCmd(0x24); ////Write Black and White image to RAM + + // for (uint16_t i = 0; i < bw_bufsize; i++) { + // sendData(bw_buf[i]); + // } + + // sendCmd(0x26); ////Write Black and White image to RAM + + // for (uint16_t i = 0; i < bw_bufsize; i++) { + // sendData(bw_buf[i]); + // } + + // update(); +} + +void Waveshare_1in54b::partUpdate() +{ + // sendCmd(0x22); + // sendData(0x0C); + // sendCmd(0x20); + // readBusy(); +} + +void Waveshare_1in54b::partDisplay(int16_t x_start, int16_t y_start, const unsigned char *datas, int16_t PART_COLUMN, int16_t PART_LINE) +{ + // int16_t i; + // int16_t x_end, y_start1, y_start2, y_end1, y_end2; + + // x_start = x_start / 8; // + // x_end = x_start + PART_LINE / 8 - 1; + + // y_start1 = 0; + // y_start2 = y_start; + + // if (y_start >= 256) + // { + // y_start1 = y_start2 / 256; + // y_start2 = y_start2 % 256; + // } + // y_end1 = 0; + // y_end2 = y_start + PART_COLUMN - 1; + + // if (y_end2 >= 256) + // { + // y_end1 = y_end2 / 256; + // y_end2 = y_end2 % 256; + // } + + // sendCmd(0x44); // set RAM x address start/end, in page 35 + // sendData(x_start); // RAM x address start at 00h; + // sendData(x_end); // RAM x address end at 0fh(15+1)*8->128 + // sendCmd(0x45); // set RAM y address start/end, in page 35 + // sendData(y_start2); // RAM y address start at 0127h; + // sendData(y_start1); // RAM y address start at 0127h; + // sendData(y_end2); // RAM y address end at 00h; + // sendData(y_end1); // ????=0 + + // sendCmd(0x4E); // set RAM x address count to 0; + // sendData(x_start); + // sendCmd(0x4F); // set RAM y address count to 0X127; + // sendData(y_start2); + // sendData(y_start1); + + // sendCmd(0x24); // Write Black and White image to RAM + + // for (i = 0; i < PART_COLUMN * PART_LINE / 8; i++) + // { + // sendData(pgm_read_byte(&datas[i])); + // } + // partUpdate(); +} diff --git a/lib/LOLIN_EPD/src/Waveshare_1in54bv2.h b/lib/LOLIN_EPD/src/Waveshare_1in54bv2.h new file mode 100644 index 0000000000..096f052d76 --- /dev/null +++ b/lib/LOLIN_EPD/src/Waveshare_1in54bv2.h @@ -0,0 +1,91 @@ +#ifndef __Waveshare_1in54bv2_H +#define __Waveshare_1in54bv2_H + +#ifdef __AVR__ + # include +#elif defined(ESP8266) || defined(ESP32) + # include +#else // ifdef __AVR__ + # define pgm_read_byte(addr) (*(const unsigned char *)(addr)) ///< read bytes from program memory +#endif // ifdef __AVR__ + +#include "LOLIN_EPD.h" + +// EPD1IN54B commands +#define EPD1IN54B_PANEL_SETTING 0x00 +#define EPD1IN54B_POWER_SETTING 0x01 +#define EPD1IN54B_POWER_OFF 0x02 +#define EPD1IN54B_POWER_OFF_SEQUENCE_SETTING 0x03 +#define EPD1IN54B_POWER_ON 0x04 +#define EPD1IN54B_POWER_ON_MEASURE 0x05 +#define EPD1IN54B_BOOSTER_SOFT_START 0x06 +#define EPD1IN54B_DEEP_SLEEP 0x07 +#define EPD1IN54B_DATA_START_TRANSMISSION_1 0x10 +#define EPD1IN54B_DATA_STOP 0x11 +#define EPD1IN54B_DISPLAY_REFRESH 0x12 +#define EPD1IN54B_DATA_START_TRANSMISSION_2 0x13 +#define EPD1IN54B_PLL_CONTROL 0x30 +#define EPD1IN54B_TEMPERATURE_SENSOR_COMMAND 0x40 +#define EPD1IN54B_TEMPERATURE_SENSOR_CALIBRATION 0x41 +#define EPD1IN54B_TEMPERATURE_SENSOR_WRITE 0x42 +#define EPD1IN54B_TEMPERATURE_SENSOR_READ 0x43 +#define EPD1IN54B_VCOM_AND_DATA_INTERVAL_SETTING 0x50 +#define EPD1IN54B_LOW_POWER_DETECTION 0x51 +#define EPD1IN54B_TCON_SETTING 0x60 +#define EPD1IN54B_TCON_RESOLUTION 0x61 +#define EPD1IN54B_SOURCE_AND_GATE_START_SETTING 0x62 +#define EPD1IN54B_GET_STATUS 0x71 +#define EPD1IN54B_AUTO_MEASURE_VCOM 0x80 +#define EPD1IN54B_VCOM_VALUE 0x81 +#define EPD1IN54B_VCM_DC_SETTING_REGISTER 0x82 +#define EPD1IN54B_PROGRAM_MODE 0xA0 +#define EPD1IN54B_ACTIVE_PROGRAM 0xA1 +#define EPD1IN54B_READ_OTP_DATA 0xA2 + +/**************************************************************************/ + +/*! + @brief Class for interfacing with Waveshare 1.54" 200x200 drivers + */ + +/**************************************************************************/ +class Waveshare_1in54b : public LOLIN_EPD { +public: + + Waveshare_1in54b(int width, + int height, + int8_t DC, + int8_t RST, + int8_t CS, + int8_t BUSY = -1); + + void begin(bool reset = true); + + void drawPixel(int16_t x, + int16_t y, + uint16_t color); + + void display(); + void update(); + + void clearBuffer(); + void clearDisplay(); + + void deepSleep(); + + void partBaseImg(); + void partInit(); + void partDisplay(int16_t x_start, + int16_t y_start, + const unsigned char *datas, + int16_t PART_COLUMN, + int16_t PART_LINE); + void partUpdate(); + +protected: + + void readBusy(); + int _height_8bit; // height 8-bit alignment +}; + +#endif // ifndef __Waveshare_1in54bv2_H diff --git a/lib/LOLIN_EPD/src/Waveshare_2in7.cpp b/lib/LOLIN_EPD/src/Waveshare_2in7.cpp index 12b73cee3d..0bc3a5d943 100644 --- a/lib/LOLIN_EPD/src/Waveshare_2in7.cpp +++ b/lib/LOLIN_EPD/src/Waveshare_2in7.cpp @@ -270,16 +270,10 @@ void Waveshare_2in7::drawPixel(int16_t x, int16_t y, uint16_t color) { // make our buffer happy x = (x == 0 ? 1 : x); - // uint16_t addr = (x * height() + y) / 8; uint16_t addr = (x + _height_8bit * y) / 8; - // if (color == EPD_RED) { - // pBuf = red_buf + addr; - // } else { pBuf = bw_buf + addr; - // } - // x is which column switch (color) { case EPD_WHITE: diff --git a/src/_P096_eInk.ino b/src/_P096_eInk.ino index 3f0489f93e..e57f954c2b 100644 --- a/src/_P096_eInk.ino +++ b/src/_P096_eInk.ino @@ -7,18 +7,25 @@ # define PLUGIN_096 # define PLUGIN_ID_096 96 -# define PLUGIN_NAME_096 "Display - eInk with Lolin ePaper screen" +# define PLUGIN_NAME_096 "Display - eInk/ePaper screens" # define PLUGIN_VALUENAME1_096 "CursorX" # define PLUGIN_VALUENAME2_096 "CursorY" -// #define PLUGIN_096_MAX_DISPLAY 1 // Unused +/** Changelog + * 2022-08-19 tonhuisman: Add support for MH-IT Live 1.54"200x200pc white/black/red display (untested) + * 2022-03 tonhuisman: Add support for Waveshare 2.7" 264x176px monochrome display + * Add support for Waveshare 1.54" 200x200px monochrome display (untested) + * Pre-2022-03: No changelog registered + * Plugin uses AdafruitGFX_Helper write command handling for drawing shapes and text on the display. + * Uses an extended version of LOLIN_EPD library, that has support for IL3897, UC8151D and SSD1680, and is extended for + * Waveshare 2.7" 264x176px monochrome, Waveshare 1.54" (B) 200x200px white/black/red and MH-IT Live 200x200px white/black/red displays + */ /* README.MD - ## INTRO - This plugin allow to control a eInk screen (ILI3897) through HTTP API + This plugin allow to control a eInk screen (IL3897) through HTTP API ## Environment Tested with Lolin d32 pro and Wemos ePaper 2.13 shield @@ -112,60 +119,17 @@ // #include "src/Helpers/AdafruitGFX_helper.h" // #endif -# ifndef P096_USE_ADA_GRAPHICS - -// declare functions for using default value parameters -void Plugin_096_printText(const char *string, - int X, - int Y, - unsigned int textSize = 1, - unsigned short color = EPD_WHITE, - unsigned short bkcolor = EPD_BLACK); -# endif // ifndef P096_USE_ADA_GRAPHICS - -// Define the default values for both ESP32/lolin32 and D1 Mini -# ifdef ESP32 - -// for D32 Pro with EPD connector - # define EPD_CS 14 - # define EPD_CS_HSPI 26 // when connected to Hardware-SPI GPIO-14 is already used - # define EPD_DC 27 - # define EPD_RST 33 // can set to -1 and share with microcontroller Reset! - # define EPD_BUSY -1 // can set to -1 to not use a pin (will wait a fixed delay) -# else // ifdef ESP32 - -// for D1 Mini with shield connection - # define EPD_CS 16 // D0 - # define EPD_DC 15 // D8 - # define EPD_RST -1 // can set to -1 and share with microcontroller Reset! - # define EPD_BUSY -1 // can set to -1 to not use a pin (will wait a fixed delay) -# endif // ifdef ESP32 - - -// // The setting structure -// struct Plugin_096_EPD_SettingStruct -// { -// Plugin_096_EPD_SettingStruct() -// : address_epd_cs(EPD_CS), address_epd_dc(EPD_DC), address_epd_rst(EPD_RST), address_epd_busy(EPD_BUSY), rotation(0), width(250), -// height( -// 122) -// {} - -// uint8_t address_epd_cs; -// uint8_t address_epd_dc; -// uint8_t address_epd_rst; -// uint8_t address_epd_busy; -// uint8_t rotation; -// int width; -// int height; -// } EPD_Settings; - -// // The display pointer -// LOLIN_IL3897 *eInkScreen = nullptr; -// uint8_t plugin_096_sequence_in_progress = false; -// # ifdef P096_USE_ADA_GRAPHICS -// AdafruitGFX_helper *gfxHelper = nullptr; -// # endif // ifdef P096_USE_ADA_GRAPHICS +// # ifndef P096_USE_ADA_GRAPHICS + +// // declare functions for using default value parameters +// void Plugin_096_printText(const char *string, +// int X, +// int Y, +// unsigned int textSize = 1, +// unsigned short color = EPD_WHITE, +// unsigned short bkcolor = EPD_BLACK); +// # endif // ifndef P096_USE_ADA_GRAPHICS + boolean Plugin_096(uint8_t function, struct EventStruct *event, String& string) { @@ -221,16 +185,16 @@ boolean Plugin_096(uint8_t function, struct EventStruct *event, String& string) case PLUGIN_SET_DEFAULTS: { - PIN(0) = EPD_CS; + PIN(0) = P096_EPD_CS; # ifdef ESP32 if (Settings.InitSPI == 2) { // When using ESP32 H(ardware-)SPI - PIN(0) = EPD_CS_HSPI; + PIN(0) = P096_EPD_CS_HSPI; } # endif // ifdef ESP32 - PIN(1) = EPD_DC; - PIN(2) = EPD_RST; - PIN(3) = EPD_BUSY; + PIN(1) = P096_EPD_DC; + PIN(2) = P096_EPD_RST; + PIN(3) = P096_EPD_BUSY; # if P096_USE_EXTENDED_SETTINGS P096_CONFIG_COLORS = static_cast(AdaGFXMonoRedGreyscaleColors::ADAGFXEPD_BLACK) | // Default to dark on white (paper) colors @@ -267,24 +231,36 @@ boolean Plugin_096(uint8_t function, struct EventStruct *event, String& string) { const __FlashStringHelper *options4[] = { - EPD_type_toString(EPD_type_e::EPD_IL3897), - EPD_type_toString(EPD_type_e::EPD_UC8151D), - EPD_type_toString(EPD_type_e::EPD_SSD1680), + toString(EPD_type_e::EPD_IL3897), + toString(EPD_type_e::EPD_UC8151D), + toString(EPD_type_e::EPD_SSD1680), # if P096_USE_WAVESHARE_2IN7 - EPD_type_toString(EPD_type_e::EPD_WS2IN7) + toString(EPD_type_e::EPD_WS2IN7), # endif // if P096_USE_WAVESHARE_2IN7 + # if P096_USE_WAVESHARE_1IN54B + toString(EPD_type_e::EPD_WS1IN54B), + # endif // if P096_USE_WAVESHARE_1IN54B + # if P096_USE_MH_ET_LIVE_1IN54 + toString(EPD_type_e::EPD_MHET1IN54), + # endif // if P096_USE_MH_ET_LIVE_1IN54 }; const int optionValues4[] = { static_cast(EPD_type_e::EPD_IL3897), static_cast(EPD_type_e::EPD_UC8151D), static_cast(EPD_type_e::EPD_SSD1680), # if P096_USE_WAVESHARE_2IN7 - static_cast(EPD_type_e::EPD_WS2IN7) + static_cast(EPD_type_e::EPD_WS2IN7), # endif // if P096_USE_WAVESHARE_2IN7 + # if P096_USE_WAVESHARE_1IN54B + static_cast(EPD_type_e::EPD_WS1IN54B), + # endif // if P096_USE_WAVESHARE_1IN54B + # if P096_USE_MH_ET_LIVE_1IN54 + static_cast(EPD_type_e::EPD_MHET1IN54), + # endif // if P096_USE_MH_ET_LIVE_1IN54 }; addFormSelector(F("eInk display model"), F("_type"), - static_cast(EPD_type_e::EPD_MAX), + sizeof(optionValues4)/sizeof(optionValues4[0]), options4, optionValues4, P096_CONFIG_FLAG_GET_DISPLAYTYPE); @@ -340,7 +316,7 @@ boolean Plugin_096(uint8_t function, struct EventStruct *event, String& string) # endif // if ADAGFX_SUPPORT_7COLOR }; - if (P096_CONFIG_FLAG_GET_COLORDEPTH == 0) { // Enum doesn't have 0 + if (P096_CONFIG_FLAG_GET_COLORDEPTH == 0) { // Enum doesn't have 0 uint32_t lSettings = 0; set4BitToUL(lSettings, P096_CONFIG_FLAG_COLORDEPTH, static_cast(AdaGFXColorDepth::Monochrome)); // Bit 20..23 Color depth P096_CONFIG_FLAGS = lSettings; @@ -359,15 +335,21 @@ boolean Plugin_096(uint8_t function, struct EventStruct *event, String& string) { const __FlashStringHelper *commandTriggers[] = { // Be sure to use all options available in the enum (except MAX)! - P096_CommandTrigger_toString(P096_CommandTrigger::epd), - P096_CommandTrigger_toString(P096_CommandTrigger::eInk), - P096_CommandTrigger_toString(P096_CommandTrigger::ePaper), - P096_CommandTrigger_toString(P096_CommandTrigger::il3897), - P096_CommandTrigger_toString(P096_CommandTrigger::uc8151d), - P096_CommandTrigger_toString(P096_CommandTrigger::ssd1680), + toString(P096_CommandTrigger::epd), + toString(P096_CommandTrigger::eInk), + toString(P096_CommandTrigger::ePaper), + toString(P096_CommandTrigger::il3897), + toString(P096_CommandTrigger::uc8151d), + toString(P096_CommandTrigger::ssd1680), # if P096_USE_WAVESHARE_2IN7 - P096_CommandTrigger_toString(P096_CommandTrigger::ws2in7) + toString(P096_CommandTrigger::ws2in7), # endif // if P096_USE_WAVESHARE_2IN7 + # if P096_USE_WAVESHARE_1IN54B + toString(P096_CommandTrigger::ws1in54b), + # endif // if P096_USE_WAVESHARE_1IN54B + # if P096_USE_MH_ET_LIVE_1IN54 + toString(P096_CommandTrigger::mhet1in54), + # endif // if P096_USE_MH_ET_LIVE_1IN54 }; const int commandTriggerOptions[] = { static_cast(P096_CommandTrigger::epd), @@ -377,12 +359,18 @@ boolean Plugin_096(uint8_t function, struct EventStruct *event, String& string) static_cast(P096_CommandTrigger::uc8151d), static_cast(P096_CommandTrigger::ssd1680), # if P096_USE_WAVESHARE_2IN7 - static_cast(P096_CommandTrigger::ws2in7) + static_cast(P096_CommandTrigger::ws2in7), # endif // if P096_USE_WAVESHARE_2IN7 + # if P096_USE_WAVESHARE_1IN54B + static_cast(P096_CommandTrigger::ws1in54b), + # endif // if P096_USE_WAVESHARE_1IN54B + # if P096_USE_MH_ET_LIVE_1IN54 + static_cast(P096_CommandTrigger::mhet1in54), + # endif // if P096_USE_MH_ET_LIVE_1IN54 }; addFormSelector(F("Write Command trigger"), F("_commandtrigger"), - static_cast(P096_CommandTrigger::MAX), + sizeof(commandTriggerOptions)/sizeof(commandTriggerOptions[0]), commandTriggers, commandTriggerOptions, P096_CONFIG_FLAG_GET_CMD_TRIGGER); @@ -512,8 +500,8 @@ boolean Plugin_096(uint8_t function, struct EventStruct *event, String& string) P096_CONFIG_ROTATION, P096_CONFIG_FLAG_GET_FONTSCALE, static_cast(P096_CONFIG_FLAG_GET_MODE), - P096_CommandTrigger_toString(static_cast( - P096_CONFIG_FLAG_GET_CMD_TRIGGER)), + toString(static_cast( + P096_CONFIG_FLAG_GET_CMD_TRIGGER)), P096_CONFIG_GET_COLOR_FOREGROUND, P096_CONFIG_GET_COLOR_BACKGROUND, static_cast(P096_CONFIG_FLAG_GET_COLORDEPTH), @@ -569,13 +557,12 @@ boolean Plugin_096(uint8_t function, struct EventStruct *event, String& string) } break; } - } return success; } -# ifndef P096_USE_ADA_GRAPHICS +// # ifndef P096_USE_ADA_GRAPHICS // Print some text // param [in] string : The text to display @@ -584,125 +571,125 @@ boolean Plugin_096(uint8_t function, struct EventStruct *event, String& string) // param [in] textSize : The text size (default 1) // param [in] color : The fore color (default ILI9341_WHITE) // param [in] bkcolor : The background color (default ILI9341_BLACK) -void Plugin_096_printText(const char *string, int X, int Y, unsigned int textSize, unsigned short color, unsigned short bkcolor) -{ - eInkScreen->clearBuffer(); - eInkScreen->clearDisplay(); - eInkScreen->setCursor(X, Y); - eInkScreen->setTextColor(color, bkcolor); - eInkScreen->setTextSize(textSize); - String fixString = string; - - Plugin_096_FixText(fixString); - eInkScreen->println(fixString); - eInkScreen->display(); -} +// void Plugin_096_printText(const char *string, int X, int Y, unsigned int textSize, unsigned short color, unsigned short bkcolor) +// { +// eInkScreen->clearBuffer(); +// eInkScreen->clearDisplay(); +// eInkScreen->setCursor(X, Y); +// eInkScreen->setTextColor(color, bkcolor); +// eInkScreen->setTextSize(textSize); +// String fixString = string; + +// Plugin_096_FixText(fixString); +// eInkScreen->println(fixString); +// eInkScreen->display(); +// } -# endif // ifndef P096_USE_ADA_GRAPHICS +// # endif // ifndef P096_USE_ADA_GRAPHICS // Parse color string to color // param [in] colorString : The color string (white, red, ...) // return : color (default EPD_WHITE) -unsigned short Plugin_096_ParseColor(const String& colorString) -{ - // copy to local var and ensure lowercase - // this optimise the next equlaity checks - String s = colorString; - - s.toLowerCase(); - - if (equals(s, F("black"))) { - return EPD_BLACK; - } - - if (equals(s, F("white"))) { - return EPD_WHITE; - } +// unsigned short Plugin_096_ParseColor(const String& colorString) +// { +// // copy to local var and ensure lowercase +// // this optimise the next equlaity checks +// String s = colorString; - if (equals(s, F("inverse"))) { - return EPD_INVERSE; - } +// s.toLowerCase(); - if (equals(s, F("red"))) { - return EPD_RED; - } +// if (equals(s, F("black"))) { +// return EPD_BLACK; +// } - if (equals(s, F("dark"))) { - return EPD_DARK; - } +// if (equals(s, F("white"))) { +// return EPD_WHITE; +// } - if (equals(s, F("light"))) { - return EPD_LIGHT; - } - return EPD_WHITE; -} +// if (equals(s, F("inverse"))) { +// return EPD_INVERSE; +// } -# ifndef P096_USE_ADA_GRAPHICS +// if (equals(s, F("red"))) { +// return EPD_RED; +// } -// Fix text with handling special characters (degrees and main monetary symbols) -// This is specific case for current AdafruitGfx standard fontused for eink screen -// param [in/out] s : The string to fix -void Plugin_096_FixText(String& s) -{ - const char degree[3] = { 0xc2, 0xb0, 0 }; // Unicode degree symbol - const char degree_eink[2] = { 0xf7, 0 }; // eink degree symbol +// if (equals(s, F("dark"))) { +// return EPD_DARK; +// } - s.replace(degree, degree_eink); - s.replace(F("{D}"), degree_eink); - s.replace(F("°"), degree_eink); +// if (equals(s, F("light"))) { +// return EPD_LIGHT; +// } +// return EPD_WHITE; +// } - const char euro[4] = { 0xe2, 0x82, 0xac, 0 }; // Unicode euro symbol - const char euro_eink[2] = { 0xED, 0 }; // eink degree symbol +// # ifndef P096_USE_ADA_GRAPHICS - s.replace(euro, euro_eink); - s.replace(F("{E}"), euro_eink); - s.replace(F("€"), euro_eink); +// // Fix text with handling special characters (degrees and main monetary symbols) +// // This is specific case for current AdafruitGfx standard fontused for eink screen +// // param [in/out] s : The string to fix +// void Plugin_096_FixText(String& s) +// { +// const char degree[3] = { 0xc2, 0xb0, 0 }; // Unicode degree symbol +// const char degree_eink[2] = { 0xf7, 0 }; // eink degree symbol - const char pound[3] = { 0xc2, 0xa3, 0 }; // Unicode pound symbol - const char pound_eink[2] = { 0x9C, 0 }; // eink pound symbol +// s.replace(degree, degree_eink); +// s.replace(F("{D}"), degree_eink); +// s.replace(F("°"), degree_eink); - s.replace(pound, pound_eink); - s.replace(F("{P}"), pound_eink); - s.replace(F("£"), pound_eink); +// const char euro[4] = { 0xe2, 0x82, 0xac, 0 }; // Unicode euro symbol +// const char euro_eink[2] = { 0xED, 0 }; // eink degree symbol - const char yen[3] = { 0xc2, 0xa5, 0 }; // Unicode yen symbol - const char yen_eink[2] = { 0x9D, 0 }; // eink yen symbol +// s.replace(euro, euro_eink); +// s.replace(F("{E}"), euro_eink); +// s.replace(F("€"), euro_eink); - s.replace(yen, yen_eink); - s.replace(F("{Y}"), yen_eink); - s.replace(F("¥"), yen_eink); +// const char pound[3] = { 0xc2, 0xa3, 0 }; // Unicode pound symbol +// const char pound_eink[2] = { 0x9C, 0 }; // eink pound symbol - const char cent[3] = { 0xc2, 0xa2, 0 }; // Unicode yen symbol - const char cent_eink[2] = { 0x9B, 0 }; // eink cent symbol +// s.replace(pound, pound_eink); +// s.replace(F("{P}"), pound_eink); +// s.replace(F("£"), pound_eink); - s.replace(cent, cent_eink); - s.replace(F("{c}"), cent_eink); - s.replace(F("¢"), cent_eink); -} +// const char yen[3] = { 0xc2, 0xa5, 0 }; // Unicode yen symbol +// const char yen_eink[2] = { 0x9D, 0 }; // eink yen symbol -// Split a string by delimiter -// param [in] s : The input string -// param [in] c : The delimiter -// param [out] op : The resulting string array -// param [in] limit : The maximum strings to find -// return : The string count -int Plugin_096_StringSplit(const String& s, char c, String op[], int limit) -{ - int count = 0; - char *pch; - String d = String(c); +// s.replace(yen, yen_eink); +// s.replace(F("{Y}"), yen_eink); +// s.replace(F("¥"), yen_eink); - pch = strtok((char *)(s.c_str()), d.c_str()); +// const char cent[3] = { 0xc2, 0xa2, 0 }; // Unicode yen symbol +// const char cent_eink[2] = { 0x9B, 0 }; // eink cent symbol - while (pch != NULL && count < limit) - { - op[count] = String(pch); - count++; - pch = strtok(NULL, ","); - } - return count; -} +// s.replace(cent, cent_eink); +// s.replace(F("{c}"), cent_eink); +// s.replace(F("¢"), cent_eink); +// } -# endif // ifndef P096_USE_ADA_GRAPHICS +// // Split a string by delimiter +// // param [in] s : The input string +// // param [in] c : The delimiter +// // param [out] op : The resulting string array +// // param [in] limit : The maximum strings to find +// // return : The string count +// int Plugin_096_StringSplit(const String& s, char c, String op[], int limit) +// { +// int count = 0; +// char *pch; +// String d = String(c); + +// pch = strtok((char *)(s.c_str()), d.c_str()); + +// while (pch != NULL && count < limit) +// { +// op[count] = String(pch); +// count++; +// pch = strtok(NULL, ","); +// } +// return count; +// } + +// # endif // ifndef P096_USE_ADA_GRAPHICS #endif // USES_P096 diff --git a/src/src/PluginStructs/P096_data_struct.cpp b/src/src/PluginStructs/P096_data_struct.cpp index 134898cf71..80486b31d7 100644 --- a/src/src/PluginStructs/P096_data_struct.cpp +++ b/src/src/PluginStructs/P096_data_struct.cpp @@ -4,25 +4,30 @@ /**************************************************************************** - * EPD_type_toString: Display-value for the device selected + * toString: Display-value for the EPD/eInk device selected ***************************************************************************/ -const __FlashStringHelper* EPD_type_toString(EPD_type_e device) { +const __FlashStringHelper* toString(EPD_type_e device) { switch (device) { case EPD_type_e::EPD_IL3897: return F("IL3897 (Lolin 250 x 122px)"); - case EPD_type_e::EPD_UC8151D: return F("UC8151D (212 x 104px)"); + case EPD_type_e::EPD_UC8151D: return F("UC8151D (white/black/red 212 x 104px)"); case EPD_type_e::EPD_SSD1680: return F("SSD1680 (250 x 212px)"); # if P096_USE_WAVESHARE_2IN7 case EPD_type_e::EPD_WS2IN7: return F("Waveshare 2.7\" (264 x 176px)"); # endif // if P096_USE_WAVESHARE_2IN7 - case EPD_type_e::EPD_MAX: break; + # if P096_USE_WAVESHARE_1IN54B + case EPD_type_e::EPD_WS1IN54B: return F("Waveshare 1.54\" (200 x 200px)"); + # endif // if P096_USE_WAVESHARE_1IN54B + # if P096_USE_MH_ET_LIVE_1IN54 + case EPD_type_e::EPD_MHET1IN54: return F("MH-ET Live 1.54\" (white/black/red 200 x 200px)"); + # endif // if P096_USE_MH_ET_LIVE_1IN54 } return F("Unsupported type!"); } /**************************************************************************** - * P096_CommandTrigger_toString: return the command string selected + * toString: return the command string selected ***************************************************************************/ -const __FlashStringHelper* P096_CommandTrigger_toString(P096_CommandTrigger cmd) { +const __FlashStringHelper* toString(P096_CommandTrigger cmd) { switch (cmd) { case P096_CommandTrigger::eInk: return F("eink"); case P096_CommandTrigger::ePaper: return F("epaper"); @@ -32,7 +37,12 @@ const __FlashStringHelper* P096_CommandTrigger_toString(P096_CommandTrigger cmd) # if P096_USE_WAVESHARE_2IN7 case P096_CommandTrigger::ws2in7: return F("ws2in7"); # endif // if P096_USE_WAVESHARE_2IN7 - case P096_CommandTrigger::MAX: return F("None"); + # if P096_USE_WAVESHARE_1IN54B + case P096_CommandTrigger::ws1in54b: return F("ws1in54"); + # endif // if P096_USE_WAVESHARE_1IN54B + # if P096_USE_MH_ET_LIVE_1IN54 + case P096_CommandTrigger::mhet1in54: return F("mhet1in54"); + # endif // if P096_USE_MH_ET_LIVE_1IN54 case P096_CommandTrigger::epd: break; } return F("epd"); // Default command trigger @@ -58,8 +68,20 @@ void EPD_type_toResolution(EPD_type_e device, uint16_t& x, uint16_t& y) { y = 176; break; # endif // if P096_USE_WAVESHARE_2IN7 - case EPD_type_e::EPD_MAX: + # if P096_USE_WAVESHARE_1IN54B + case EPD_type_e::EPD_WS1IN54B: + x = 200; + y = 200; break; + # endif // if P096_USE_WAVESHARE_1IN54B + # if P096_USE_MH_ET_LIVE_1IN54 + case EPD_type_e::EPD_MHET1IN54: + x = 200; + y = 200; + break; + # endif // if P096_USE_MH_ET_LIVE_1IN54 + // case EPD_type_e::EPD_MAX: + // break; } } @@ -119,103 +141,110 @@ bool P096_data_struct::plugin_init(struct EventStruct *event) { bool success = false; - if (nullptr == eInkScreen) { - addLog(LOG_LEVEL_INFO, F("EPD : Init start.")); - - switch (_display) { - case EPD_type_e::EPD_IL3897: - eInkScreen = new (std::nothrow) LOLIN_IL3897(_xpix, _ypix, PIN(1), PIN(2), PIN(0), PIN(3)); // HSPI - break; - case EPD_type_e::EPD_UC8151D: - eInkScreen = new (std::nothrow) LOLIN_UC8151D(_xpix, _ypix, PIN(1), PIN(2), PIN(0), PIN(3)); // HSPI - break; - case EPD_type_e::EPD_SSD1680: - eInkScreen = new (std::nothrow) LOLIN_SSD1680(_xpix, _ypix, PIN(1), PIN(2), PIN(0), PIN(3)); // HSPI - break; + addLog(LOG_LEVEL_INFO, F("EPD : Init start.")); + + switch (_display) { + case EPD_type_e::EPD_IL3897: + eInkScreen = new (std::nothrow) LOLIN_IL3897(_xpix, _ypix, PIN(1), PIN(2), PIN(0), PIN(3)); // HSPI + break; + case EPD_type_e::EPD_UC8151D: + eInkScreen = new (std::nothrow) LOLIN_UC8151D(_xpix, _ypix, PIN(1), PIN(2), PIN(0), PIN(3)); // HSPI + break; + case EPD_type_e::EPD_SSD1680: + eInkScreen = new (std::nothrow) LOLIN_SSD1680(_xpix, _ypix, PIN(1), PIN(2), PIN(0), PIN(3)); // HSPI + break; # if P096_USE_WAVESHARE_2IN7 - case EPD_type_e::EPD_WS2IN7: - eInkScreen = new (std::nothrow) Waveshare_2in7(_xpix, _ypix, PIN(1), PIN(2), PIN(0), PIN(3)); // HSPI - break; + case EPD_type_e::EPD_WS2IN7: + eInkScreen = new (std::nothrow) Waveshare_2in7(_xpix, _ypix, PIN(1), PIN(2), PIN(0), PIN(3)); // HSPI + break; # endif // if P096_USE_WAVESHARE_2IN7 - case EPD_type_e::EPD_MAX: - break; - } - plugin_096_sequence_in_progress = false; - # ifdef P096_USE_ADA_GRAPHICS - - if (nullptr != eInkScreen) { - gfxHelper = new (std::nothrow) AdafruitGFX_helper(eInkScreen, - _commandTrigger, - _xpix, - _ypix, - _colorDepth, - _textmode, - _fontscaling, - _fgcolor, - _bgcolor, - true, - _textBackFill); - # if P096_USE_EXTENDED_SETTINGS - - if (nullptr != gfxHelper) { - gfxHelper->initialize(); - gfxHelper->setRotation(_rotation); - gfxHelper->setColumnRowMode(bitRead(P096_CONFIG_FLAGS, P096_CONFIG_FLAG_USE_COL_ROW)); - gfxHelper->setTxtfullCompensation(!bitRead(P096_CONFIG_FLAGS, P096_CONFIG_FLAG_COMPAT_P096) ? 0 : 1); // Inverted - } - # endif // if P096_USE_EXTENDED_SETTINGS + # if P096_USE_WAVESHARE_1IN54B + case EPD_type_e::EPD_WS1IN54B: + eInkScreen = new (std::nothrow) Waveshare_1in54b(_xpix, _ypix, PIN(1), PIN(2), PIN(0), PIN(3)); // HSPI + break; + # endif // if P096_USE_WAVESHARE_1IN54B + # if P096_USE_MH_ET_LIVE_1IN54 + case EPD_type_e::EPD_MHET1IN54: + eInkScreen = new (std::nothrow) MH_ET_Live_1in54(_xpix, _ypix, PIN(1), PIN(2), PIN(0), PIN(3)); // HSPI + break; + # endif // if P096_USE_MH_ET_LIVE_1IN54 + // case EPD_type_e::EPD_MAX: + // break; + } + _sequence_in_progress = false; + # ifdef P096_USE_ADA_GRAPHICS + + if (nullptr != eInkScreen) { + eInkScreen->begin(); // Start the device + gfxHelper = new (std::nothrow) AdafruitGFX_helper(eInkScreen, + _commandTrigger, + _xpix, + _ypix, + _colorDepth, + _textmode, + _fontscaling, + _fgcolor, + _bgcolor, + true, + _textBackFill); + # if P096_USE_EXTENDED_SETTINGS + + if (nullptr != gfxHelper) { + gfxHelper->initialize(); + gfxHelper->setRotation(_rotation); + gfxHelper->setColumnRowMode(bitRead(P096_CONFIG_FLAGS, P096_CONFIG_FLAG_USE_COL_ROW)); + gfxHelper->setTxtfullCompensation(!bitRead(P096_CONFIG_FLAGS, P096_CONFIG_FLAG_COMPAT_P096) ? 0 : 1); // Inverted } - updateFontMetrics(); - # endif // ifdef P096_USE_ADA_GRAPHICS + # endif // if P096_USE_EXTENDED_SETTINGS + } + updateFontMetrics(); + # endif // ifdef P096_USE_ADA_GRAPHICS - # ifndef BUILD_NO_DEBUG + # ifndef BUILD_NO_DEBUG - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - String log; - log.reserve(50); - log += F("EPD : Init done, address: 0x"); - log += String(reinterpret_cast(eInkScreen), HEX); - log += ' '; + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + String log; + log.reserve(50); + log += F("EPD : Init done, address: "); + log += formatToHex(reinterpret_cast(eInkScreen)); + log += ' '; - if (nullptr == eInkScreen) { - log += F("in"); - } - log += F("valid, commands: "); - log += _commandTrigger; - log += F(", display: "); - log += EPD_type_toString(_display); - addLog(LOG_LEVEL_INFO, log); - log.clear(); - log += F("EPD : Foreground: 0x"); - log += String(_fgcolor, HEX); - log += F(", background: 0x"); - log += String(_bgcolor, HEX); - addLogMove(LOG_LEVEL_INFO, log); + if (nullptr == eInkScreen) { + log += F("in"); } - # endif // ifndef BUILD_NO_DEBUG + log += F("valid, commands: "); + log += _commandTrigger; + log += F(", display: "); + log += toString(_display); + addLog(LOG_LEVEL_INFO, log); + log.clear(); + log += F("EPD : Foreground: "); + log += AdaGFXcolorToString(_fgcolor, static_cast(P096_CONFIG_FLAG_GET_COLORDEPTH)); + log += F(", background: "); + log += AdaGFXcolorToString(_bgcolor, static_cast(P096_CONFIG_FLAG_GET_COLORDEPTH)); + addLogMove(LOG_LEVEL_INFO, log); + } + # endif // ifndef BUILD_NO_DEBUG - if (nullptr != eInkScreen) { - eInkScreen->begin(); // Start the device - eInkScreen->clearBuffer(); + if (nullptr != eInkScreen) { + eInkScreen->begin(); // Start the device + eInkScreen->clearBuffer(); - eInkScreen->setRotation(_rotation); - eInkScreen->setTextColor(_fgcolor); - eInkScreen->setTextSize(_fontscaling); // Handles 0 properly, text size, default 1 = very small - eInkScreen->setCursor(0, 0); // move cursor to position (0, 0) pixel + eInkScreen->setRotation(_rotation); + eInkScreen->setTextColor(_fgcolor); + eInkScreen->setTextSize(_fontscaling); // Handles 0 properly, text size, default 1 = very small + eInkScreen->setCursor(0, 0); // move cursor to position (0, 0) pixel - if (!stringsLoaded) { - LoadCustomTaskSettings(event->TaskIndex, strings, P096_Nlines, 0); - stringsLoaded = true; + if (!stringsLoaded) { + LoadCustomTaskSettings(event->TaskIndex, strings, P096_Nlines, 0); + stringsLoaded = true; - for (uint8_t x = 0; x < P096_Nlines && !stringsHasContent; x++) { - stringsHasContent = !strings[x].isEmpty(); - } + for (uint8_t x = 0; x < P096_Nlines && !stringsHasContent; x++) { + stringsHasContent = !strings[x].isEmpty(); } } success = true; - } else { - addLog(LOG_LEVEL_INFO, F("EPD : No init?")); } return success; @@ -283,7 +312,7 @@ bool P096_data_struct::plugin_read(struct EventStruct *event) { gfxHelper->setColumnRowMode(bitRead(P096_CONFIG_FLAGS, P096_CONFIG_FLAG_USE_COL_ROW)); // Restore column mode int16_t curX, curY; gfxHelper->getCursorXY(curX, curY); // Get current X and Y coordinates, - UserVar.setFloat(event->TaskIndex, 0, curX); // and put into Values + UserVar.setFloat(event->TaskIndex, 0, curX); // and put into Values UserVar.setFloat(event->TaskIndex, 1, curY); eInkScreen->display(); @@ -329,17 +358,18 @@ bool P096_data_struct::plugin_write(struct EventStruct *event, const String& str } else if (equals(arg1, F("deepsleep"))) { eInkScreen->deepSleep(); + success = true; } else if (equals(arg1, F("seq_start"))) { String arg2 = parseString(string, 3); eInkScreen->clearBuffer(); const uint16_t fillColor = - (arg2.isEmpty() ? static_cast(AdaGFXMonoRedGreyscaleColors::ADAGFXEPD_BLACK) + (arg2.isEmpty() ? static_cast(AdaGFXMonoRedGreyscaleColors::ADAGFXEPD_WHITE) : AdaGFXparseColor(arg2, _colorDepth)); eInkScreen->fillScreen(fillColor); - plugin_096_sequence_in_progress = true; - success = true; + _sequence_in_progress = true; + success = true; } else if (equals(arg1, F("seq_end"))) { // # ifndef BUILD_NO_DEBUG @@ -347,23 +377,14 @@ bool P096_data_struct::plugin_write(struct EventStruct *event, const String& str // const unsigned statisticsTimerStart(micros()); // # endif // ifndef BUILD_NO_DEBUG eInkScreen->display(); - - // # ifndef BUILD_NO_DEBUG - // s.add(usecPassedSince(statisticsTimerStart)); - // tmpString += "
Display timings = " + String(s.getAvg()); - // # endif // ifndef BUILD_NO_DEBUG eInkScreen->clearBuffer(); - plugin_096_sequence_in_progress = false; - success = true; + _sequence_in_progress = false; + success = true; } - else if (equals(arg1, F("inv"))) { - String arg2 = parseString(string, 3); - int32_t nArg2; - - if (validIntFromString(arg2, nArg2) && - (nArg2 >= 0) && - (nArg2 <= 1)) { - eInkScreen->invertDisplay(nArg2); + else if (arg1.equals(F("inv"))) { + if ((event->Par2 >= 0) && + (event->Par2 <= 1)) { + eInkScreen->invertDisplay(event->Par2); eInkScreen->display(); success = true; } @@ -371,12 +392,8 @@ bool P096_data_struct::plugin_write(struct EventStruct *event, const String& str else if (equals(arg1, F("rot"))) { ///control?cmd=epdcmd,rot,0 // not working to verify - String arg2 = parseString(string, 3); - int32_t nArg2; - - if (validIntFromString(arg2, nArg2) && - (nArg2 >= 0)) { - eInkScreen->setRotation(nArg2 % 4); + if ((event->Par2 >= 0)) { + eInkScreen->setRotation(event->Par2 % 4); eInkScreen->display(); success = true; } @@ -388,14 +405,10 @@ bool P096_data_struct::plugin_write(struct EventStruct *event, const String& str (gfxHelper && gfxHelper->isAdaGFXTrigger(cmd)))) { success = true; - // if (!bitRead(P096_CONFIG_FLAGS, P096_CONFIG_FLAG_NO_WAKE)) { // Wake display? - // displayOnOff(true, P096_CONFIG_BACKLIGHT_PIN, P096_CONFIG_BACKLIGHT_PERCENT, P096_CONFIG_DISPLAY_TIMEOUT); - // } - if (nullptr != gfxHelper) { String tmp = string; - if (!plugin_096_sequence_in_progress) { + if (!_sequence_in_progress) { eInkScreen->clearBuffer(); eInkScreen->fillScreen(EPD_WHITE); } @@ -403,10 +416,8 @@ bool P096_data_struct::plugin_write(struct EventStruct *event, const String& str // Hand it over after replacing variables success = gfxHelper->processCommand(AdaGFXparseTemplate(tmp, _textcols, gfxHelper)); - if (success && !plugin_096_sequence_in_progress) { + if (success && !_sequence_in_progress) { eInkScreen->display(); - - // eInkScreen->clearBuffer(); } updateFontMetrics(); // Font or color may have changed diff --git a/src/src/PluginStructs/P096_data_struct.h b/src/src/PluginStructs/P096_data_struct.h index d3f52f7ea8..75d093b5c1 100644 --- a/src/src/PluginStructs/P096_data_struct.h +++ b/src/src/PluginStructs/P096_data_struct.h @@ -4,33 +4,39 @@ #include "../../_Plugin_Helper.h" #ifdef USES_P096 -# include // include Adafruit graphics library -# include // include Adafruit Lolin eInk/ePaper library +# include // include Adafruit graphics library +# include // include Adafruit Lolin eInk/ePaper library -# define P096_USE_ADA_GRAPHICS // Use AdafruitGFX_helper +# define P096_USE_ADA_GRAPHICS // Use AdafruitGFX_helper # ifndef P096_USE_EXTENDED_SETTINGS -# define P096_USE_EXTENDED_SETTINGS 1 // Allow more settings/options, made available by the AdaGFX helper +# define P096_USE_EXTENDED_SETTINGS 1 // Allow more settings/options, made available by the AdaGFX helper # endif // ifndef P096_USE_EXTENDED_SETTINGS -# if !P096_USE_WAVESHARE_2IN7 -# define P096_USE_WAVESHARE_2IN7 1 // Include the Waveshare 2.7 inch ePaper display -# endif // if !P096_USE_WAVESHARE_2IN7 - -# include "../Helpers/AdafruitGFX_helper.h" // Use Adafruit graphics helper objecr +# ifndef P096_USE_WAVESHARE_2IN7 +# define P096_USE_WAVESHARE_2IN7 1 // Include the Waveshare 2.7 inch ePaper display +# endif // ifndef P096_USE_WAVESHARE_2IN7 +# ifndef P096_USE_WAVESHARE_1IN54B +# define P096_USE_WAVESHARE_1IN54B 1 // Include the Waveshare 1.54 inch 200x200 ePaper display +# endif // ifndef P096_USE_WAVESHARE_1IN54B +# ifndef P096_USE_MH_ET_LIVE_1IN54 +# define P096_USE_MH_ET_LIVE_1IN54 1 // Include the MH-ET Live 1.54 inch 200x200 white/black/red ePaper display +# endif // ifndef P096_USE_MH_ET_LIVE_1IN54 + +# include "../Helpers/AdafruitGFX_helper.h" // Use Adafruit graphics helper objecr # include "../CustomBuild/StorageLayout.h" -# define P096_Nlines 24 // The number of different lines which can be displayed +# define P096_Nlines 24 // The number of different lines which can be displayed # define P096_Nchars 60 -# define P096_CONFIG_VERSION PCONFIG(0) // Settings version -# define P096_CONFIG_ROTATION PCONFIG(1) // Rotation -# define P096_CONFIG_WIDTH PCONFIG(2) // Display width -# define P096_CONFIG_HEIGHT PCONFIG(3) // Display height +# define P096_CONFIG_VERSION PCONFIG(0) // Settings version +# define P096_CONFIG_ROTATION PCONFIG(1) // Rotation +# define P096_CONFIG_WIDTH PCONFIG(2) // Display width +# define P096_CONFIG_HEIGHT PCONFIG(3) // Display height -# define P096_CONFIG_COLORS PCONFIG_ULONG(3) // 2 Colors fit in 1 long +# define P096_CONFIG_COLORS PCONFIG_ULONG(3) // 2 Colors fit in 1 long -# define P096_CONFIG_FLAGS PCONFIG_ULONG(0) // All flags, 32 bits available +# define P096_CONFIG_FLAGS PCONFIG_ULONG(0) // All flags, 32 bits available // # define P096_CONFIG_FLAG_NO_WAKE 0 // Flag: Don't wake display // # define P096_CONFIG_FLAG_INVERT_BUTTON 1 // Flag: Inverted button state // # define P096_CONFIG_FLAG_CLEAR_ON_EXIT 2 // Flag: Clear display on exit @@ -55,16 +61,18 @@ # ifdef ESP32 // for D32 Pro with TFT connector - # define P096_TFT_CS 14 - # define P096_TFT_CS_HSPI 26 // when connected to Hardware-SPI GPIO-14 is already used - # define P096_TFT_DC 27 - # define P096_TFT_RST -1 // 33 + # define P096_EPD_CS 14 + # define P096_EPD_CS_HSPI 26 // when connected to Hardware-SPI GPIO-14 is already used + # define P096_EPD_DC 27 + # define P096_EPD_RST -1 // 33 + # define P096_EPD_BUSY -1 # else // ifdef ESP32 // Was: for D1 Mini with shield connection - # define P096_TFT_CS D3 // 0 // D0 - # define P096_TFT_DC D2 // 4 // D8 - # define P096_TFT_RST -1 // D4 // -1 + # define P096_EPD_CS 15 // D8 + # define P096_EPD_DC 2 // D4 + # define P096_EPD_RST -1 // D4 // -1 + # define P096_EPD_BUSY -1 # endif // ifdef ESP32 enum class EPD_type_e : uint8_t { @@ -74,7 +82,12 @@ enum class EPD_type_e : uint8_t { # if P096_USE_WAVESHARE_2IN7 EPD_WS2IN7 = 3u, # endif // if P096_USE_WAVESHARE_2IN7 - EPD_MAX // must be last value in enum + # if P096_USE_WAVESHARE_1IN54B + EPD_WS1IN54B = 4u, + # endif // if P096_USE_WAVESHARE_1IN54B + # if P096_USE_MH_ET_LIVE_1IN54 + EPD_MHET1IN54 = 5u, + # endif // if P096_USE_MH_ET_LIVE_1IN54 }; enum class P096_CommandTrigger : uint8_t { @@ -87,12 +100,16 @@ enum class P096_CommandTrigger : uint8_t { # if P096_USE_WAVESHARE_2IN7 ws2in7 = 6u, # endif // if P096_USE_WAVESHARE_2IN7 - - MAX // Keep as last item! + # if P096_USE_WAVESHARE_1IN54B + ws1in54b = 7u, + # endif // if P096_USE_WAVESHARE_1IN54B + # if P096_USE_MH_ET_LIVE_1IN54 + mhet1in54 = 8u, + # endif // if P096_USE_MH_ET_LIVE_1IN54 }; -const __FlashStringHelper* EPD_type_toString(EPD_type_e device); -const __FlashStringHelper* P096_CommandTrigger_toString(P096_CommandTrigger cmd); +const __FlashStringHelper* toString(EPD_type_e device); +const __FlashStringHelper* toString(P096_CommandTrigger cmd); void EPD_type_toResolution(EPD_type_e device, uint16_t & x, uint16_t & y); @@ -109,8 +126,8 @@ struct P096_data_struct : public PluginTaskData_base { uint8_t fontscaling, AdaGFXTextPrintMode textmode, String commandTrigger, - uint16_t fgcolor = ADAGFX_WHITE, - uint16_t bgcolor = ADAGFX_BLACK, + uint16_t fgcolor = ADAGFX_BLACK, + uint16_t bgcolor = ADAGFX_WHITE, AdaGFXColorDepth colorDepth = AdaGFXColorDepth::Monochrome, bool textBackFill = true); P096_data_struct() = delete; @@ -130,7 +147,7 @@ struct P096_data_struct : public PluginTaskData_base { AdafruitGFX_helper *gfxHelper = nullptr; - bool plugin_096_sequence_in_progress = false; + bool _sequence_in_progress = false; EPD_type_e _display; uint16_t _xpix = 0;