[P096] Add support for Waveshare 2in7 264x176 pixel monochrome ePaper display

This commit is contained in:
Ton Huisman
2022-03-23 21:25:27 +01:00
parent 5c0b234490
commit 29ca2268fe
7 changed files with 713 additions and 306 deletions
+3 -1
View File
@@ -48,7 +48,9 @@ LOLIN_EPD::~LOLIN_EPD()
{
free(bw_buf);
free(red_buf);
if (red_buf) {
free(red_buf);
}
}
/**************************************************************************/
+3 -2
View File
@@ -87,8 +87,8 @@ protected:
red_bufsize; ///< size of the red buffer
bool singleByteTxns; ///< if true CS will go high after every data byte transferred
uint8_t *bw_buf; ///< the pointer to the black and white buffer if using on-chip ram
uint8_t *red_buf; ///< the pointer to the red buffer if using on-chip ram
uint8_t *bw_buf = nullptr; ///< the pointer to the black and white buffer if using on-chip ram
uint8_t *red_buf = nullptr; ///< the pointer to the red buffer if using on-chip ram
void sendCmd(uint8_t c);
void sendData(uint8_t data);
@@ -116,5 +116,6 @@ private:
#include "LOLIN_IL3897.h"
#include "LOLIN_UC8151D.h"
#include "LOLIN_SSD1680.h"
#include "Waveshare_2in7.h"
#endif
+528
View File
@@ -0,0 +1,528 @@
#include "LOLIN_EPD.h"
#include "Waveshare_2in7.h"
#define ALLSCREEN_GRAGHBYTES 4000
///////////////////////////////////////////////////
/////////////////EPD settings Functions/////////////////////
/////////////////////////////////////LUT//////////////////////////////////////////////
static const unsigned char EPD_2in7_gray_lut_vcom[] = {
0x00, 0x00,
0x00, 0x0A,0x00, 0x00, 0x00, 0x01,
0x60, 0x14,0x14, 0x00, 0x00, 0x01,
0x00, 0x14,0x00, 0x00, 0x00, 0x01,
0x00, 0x13,0x0A, 0x01, 0x00, 0x01,
0x00, 0x00,0x00, 0x00, 0x00, 0x00,
0x00, 0x00,0x00, 0x00, 0x00, 0x00,
0x00, 0x00,0x00, 0x00, 0x00, 0x00,
};
// R21
static const unsigned char EPD_2in7_gray_lut_ww[] = {
0x40, 0x0A, 0x00, 0x00, 0x00, 0x01,
0x90, 0x14, 0x14, 0x00, 0x00, 0x01,
0x10, 0x14, 0x0A, 0x00, 0x00, 0x01,
0xA0, 0x13, 0x01, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
// R22H r
static const unsigned char EPD_2in7_gray_lut_bw[] = {
0x40, 0x0A, 0x00, 0x00, 0x00, 0x01,
0x90, 0x14, 0x14, 0x00, 0x00, 0x01,
0x00, 0x14, 0x0A, 0x00, 0x00, 0x01,
0x99, 0x0C, 0x01, 0x03, 0x04, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
// R23H w
static const unsigned char EPD_2in7_gray_lut_wb[] = {
0x40, 0x0A, 0x00, 0x00, 0x00, 0x01,
0x90, 0x14, 0x14, 0x00, 0x00, 0x01,
0x00, 0x14, 0x0A, 0x00, 0x00, 0x01,
0x99, 0x0B, 0x04, 0x04, 0x01, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
// R24H b
static const unsigned char EPD_2in7_gray_lut_bb[] = {
0x80, 0x0A, 0x00, 0x00, 0x00, 0x01,
0x90, 0x14, 0x14, 0x00, 0x00, 0x01,
0x20, 0x14, 0x0A, 0x00, 0x00, 0x01,
0x50, 0x13, 0x01, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
#define BUSY_WAIT 1000
/*!
@brief constructor if using on-chip RAM and software SPI
@param width the width of the display in pixels
@param height the height of the display in pixels
@param SID the SID pin to use
@param SCLK the SCLK pin to use
@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_2in7::Waveshare_2in7(int width, int height, int8_t SID, int8_t SCLK, int8_t DC, int8_t RST, int8_t CS, int8_t BUSY)
: LOLIN_EPD(width, height, SID, SCLK, 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(width * _height_8bit / 8); //
// red_bufsize = bw_bufsize;
}
Waveshare_2in7::Waveshare_2in7(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(width * _height_8bit / 8);
// 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_2in7::begin(bool reset) {
LOLIN_EPD::begin(reset);
readBusy();
sendCmd(0x12);
readBusy();
sendCmd(POWER_SETTING);
sendData(0x03); // VDS_EN, VDG_EN
sendData(0x00); // VCOM_HV, VGHL_LV[1], VGHL_LV[0]
sendData(0x2b); // VDH
sendData(0x2b); // VDL
sendData(0x09); // VDHR
sendCmd(BOOSTER_SOFT_START);
sendData(0x07);
sendData(0x07);
sendData(0x17);
// Power optimization
sendCmd(POWER_OPTIMIZATION);
sendData(0x60);
sendData(0xA5);
// Power optimization
sendCmd(POWER_OPTIMIZATION);
sendData(0x89);
sendData(0xA5);
// Power optimization
sendCmd(POWER_OPTIMIZATION);
sendData(0x90);
sendData(0x00);
// Power optimization
sendCmd(POWER_OPTIMIZATION);
sendData(0x93);
sendData(0x2A);
// Power optimization
sendCmd(POWER_OPTIMIZATION);
sendData(0xA0);
sendData(0xA5);
// Power optimization
sendCmd(POWER_OPTIMIZATION);
sendData(0xA1);
sendData(0x00);
// Power optimization
sendCmd(POWER_OPTIMIZATION);
sendData(0x73);
sendData(0x41);
sendCmd(PARTIAL_DISPLAY_REFRESH);
sendData(0x00);
sendCmd(WS2IN7_POWER_ON);
readBusy();
sendCmd(PANEL_SETTING);
sendData(0xAF); // KW-BF KWR-AF BWROTP 0f
sendCmd(PLL_CONTROL);
sendData(0x3A); // 3A 100HZ 29 150Hz 39 200HZ 31 171HZ
sendCmd(VCM_DC_SETTING_REGISTER);
sendData(0x12);
delay(2);
setLut();
/* EPD hardware init end */
readBusy();
}
/**
* @brief: set the look-up tables
*/
void Waveshare_2in7::setLut(void) {
unsigned int count;
sendCmd(LUT_FOR_VCOM); // vcom
for (count = 0; count < 44; count++) {
sendData(lut_vcom_dc[count]);
}
sendCmd(LUT_WHITE_TO_WHITE); // ww --
for (count = 0; count < 42; count++) {
sendData(lut_ww[count]);
}
sendCmd(LUT_BLACK_TO_WHITE); // bw r
for (count = 0; count < 42; count++) {
sendData(lut_bw[count]);
}
sendCmd(LUT_WHITE_TO_BLACK); // wb w
for (count = 0; count < 42; count++) {
sendData(lut_bb[count]);
}
sendCmd(LUT_BLACK_TO_BLACK); // bb b
for (count = 0; count < 42; count++) {
sendData(lut_wb[count]);
}
}
void Waveshare_2in7::display() {
// sendCmd(DATA_START_TRANSMISSION_1); // ?? write RAM for black(0)/white (1)
// delay(2);
// for (uint16_t i = 0; i < bw_bufsize; i++) {
// sendData(0xFF);
// }
// delay(2);
sendCmd(DATA_START_TRANSMISSION_2); // write RAM for black(0)/white (1)
delay(2);
for (uint16_t i = 0; i < bw_bufsize; i++) {
sendData(bw_buf[i]);
}
delay(2);
update();
}
void Waveshare_2in7::update() {
sendCmd(DISPLAY_REFRESH);
delay(200);
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_2in7::drawPixel(int16_t x, int16_t y, uint16_t color) {
uint8_t *pBuf;
// check rotation, move pixel around if necessary
switch (getRotation()) {
case 1:
EPD_swap(x, y);
x = WIDTH - x - 1;
break;
case 2:
x = WIDTH - x - 1;
y = HEIGHT - y - 1;
break;
case 3:
EPD_swap(x, y);
y = HEIGHT - y - 1;
break;
}
// Transformed to native pixels
if ((x < 0) || (x >= width()) || (y < 0) || (y >= height())) {
return;
}
// 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:
*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_2in7::clearBuffer() {
memset(bw_buf, 0xFF, bw_bufsize);
}
/**************************************************************************/
/*!
@brief clear the display twice to remove any spooky ghost images
*/
/**************************************************************************/
void Waveshare_2in7::clearDisplay() {
clearBuffer();
display();
delay(100);
display();
}
void Waveshare_2in7::readBusy() {
if (busy >= 0) {
while (1) {
if (digitalRead(busy) == 0) {
delay(1);
break;
}
delay(0);
}
} else {
delay(BUSY_WAIT);
}
}
void Waveshare_2in7::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_2in7::deepSleep() {
sendCmd(DEEP_SLEEP);
sendData(0xa5);
}
void Waveshare_2in7::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_2in7::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_2in7::partUpdate()
{
sendCmd(0x22);
sendData(0x0C);
sendCmd(0x20);
readBusy();
}
void Waveshare_2in7::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();
}
const unsigned char lut_vcom_dc[] = {
0x00, 0x00,
0x00, 0x0F,0x0F, 0x00, 0x00, 0x05,
0x00, 0x32,0x32, 0x00, 0x00, 0x02,
0x00, 0x0F,0x0F, 0x00, 0x00, 0x05,
0x00, 0x00,0x00, 0x00, 0x00, 0x00,
0x00, 0x00,0x00, 0x00, 0x00, 0x00,
0x00, 0x00,0x00, 0x00, 0x00, 0x00,
0x00, 0x00,0x00, 0x00, 0x00, 0x00,
};
// R21H
const unsigned char lut_ww[] = {
0x50, 0x0F, 0x0F, 0x00, 0x00, 0x05,
0x60, 0x32, 0x32, 0x00, 0x00, 0x02,
0xA0, 0x0F, 0x0F, 0x00, 0x00, 0x05,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
// R22H r
const unsigned char lut_bw[] =
{
0x50, 0x0F, 0x0F, 0x00, 0x00, 0x05,
0x60, 0x32, 0x32, 0x00, 0x00, 0x02,
0xA0, 0x0F, 0x0F, 0x00, 0x00, 0x05,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
// R24H b
const unsigned char lut_bb[] =
{
0xA0, 0x0F, 0x0F, 0x00, 0x00, 0x05,
0x60, 0x32, 0x32, 0x00, 0x00, 0x02,
0x50, 0x0F, 0x0F, 0x00, 0x00, 0x05,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
// R23H w
const unsigned char lut_wb[] =
{
0xA0, 0x0F, 0x0F, 0x00, 0x00, 0x05,
0x60, 0x32, 0x32, 0x00, 0x00, 0x02,
0x50, 0x0F, 0x0F, 0x00, 0x00, 0x05,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
+116
View File
@@ -0,0 +1,116 @@
#ifndef __Waveshare_2in7_H
#define __Waveshare_2in7_H
#ifdef __AVR__
# include <avr/pgmspace.h>
#elif defined(ESP8266) || defined(ESP32)
# include <pgmspace.h>
#else // ifdef __AVR__
# define pgm_read_byte(addr) (*(const unsigned char *)(addr)) ///< read bytes from program memory
#endif // ifdef __AVR__
#include "LOLIN_EPD.h"
// EPD2IN7 commands
#define PANEL_SETTING 0x00
#define POWER_SETTING 0x01
#define WS2IN7_POWER_OFF 0x02
#define POWER_OFF_SEQUENCE_SETTING 0x03
#define WS2IN7_POWER_ON 0x04
#define POWER_ON_MEASURE 0x05
#define BOOSTER_SOFT_START 0x06
#define DEEP_SLEEP 0x07
#define DATA_START_TRANSMISSION_1 0x10
#define DATA_STOP 0x11
#define DISPLAY_REFRESH 0x12
#define DATA_START_TRANSMISSION_2 0x13
#define PARTIAL_DATA_START_TRANSMISSION_1 0x14
#define PARTIAL_DATA_START_TRANSMISSION_2 0x15
#define PARTIAL_DISPLAY_REFRESH 0x16
#define LUT_FOR_VCOM 0x20
#define LUT_WHITE_TO_WHITE 0x21
#define LUT_BLACK_TO_WHITE 0x22
#define LUT_WHITE_TO_BLACK 0x23
#define LUT_BLACK_TO_BLACK 0x24
#define PLL_CONTROL 0x30
#define TEMPERATURE_SENSOR_COMMAND 0x40
#define TEMPERATURE_SENSOR_CALIBRATION 0x41
#define TEMPERATURE_SENSOR_WRITE 0x42
#define TEMPERATURE_SENSOR_READ 0x43
#define VCOM_AND_DATA_INTERVAL_SETTING 0x50
#define LOW_POWER_DETECTION 0x51
#define TCON_SETTING 0x60
#define TCON_RESOLUTION 0x61
#define SOURCE_AND_GATE_START_SETTING 0x62
#define GET_STATUS 0x71
#define AUTO_MEASURE_VCOM 0x80
#define VCOM_VALUE 0x81
#define VCM_DC_SETTING_REGISTER 0x82
#define PROGRAM_MODE 0xA0
#define ACTIVE_PROGRAM 0xA1
#define READ_OTP_DATA 0xA2
#define POWER_OPTIMIZATION 0xF8
extern const unsigned char lut_vcom_dc[];
extern const unsigned char lut_ww[];
extern const unsigned char lut_bw[];
extern const unsigned char lut_bb[];
extern const unsigned char lut_wb[];
/**************************************************************************/
/*!
@brief Class for interfacing with IL3897 EPD drivers
*/
/**************************************************************************/
class Waveshare_2in7 : public LOLIN_EPD {
public:
Waveshare_2in7(int width,
int height,
int8_t SID,
int8_t SCLK,
int8_t DC,
int8_t RST,
int8_t CS,
int8_t BUSY = -1);
Waveshare_2in7(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();
void selectLUT(uint8_t *wave_data);
void setLut();
int _height_8bit; // height 8-bit alignment
};
#endif // ifndef __Waveshare_2in7_H
+22 -290
View File
@@ -268,11 +268,19 @@ 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) };
EPD_type_toString(EPD_type_e::EPD_SSD1680),
# if P096_USE_WAVESHARE_2IN7
EPD_type_toString(EPD_type_e::EPD_WS2IN7)
# endif // if P096_USE_WAVESHARE_2IN7
};
const int optionValues4[] = {
static_cast<int>(EPD_type_e::EPD_IL3897),
static_cast<int>(EPD_type_e::EPD_UC8151D),
static_cast<int>(EPD_type_e::EPD_SSD1680) };
static_cast<int>(EPD_type_e::EPD_SSD1680),
# if P096_USE_WAVESHARE_2IN7
static_cast<int>(EPD_type_e::EPD_WS2IN7)
# endif // if P096_USE_WAVESHARE_2IN7
};
addFormSelector(F("eInk display model"),
F("p096_type"),
static_cast<int>(EPD_type_e::EPD_MAX),
@@ -355,7 +363,10 @@ boolean Plugin_096(uint8_t function, struct EventStruct *event, String& string)
P096_CommandTrigger_toString(P096_CommandTrigger::ePaper),
P096_CommandTrigger_toString(P096_CommandTrigger::il3897),
P096_CommandTrigger_toString(P096_CommandTrigger::uc8151d),
P096_CommandTrigger_toString(P096_CommandTrigger::ssd1680)
P096_CommandTrigger_toString(P096_CommandTrigger::ssd1680),
# if P096_USE_WAVESHARE_2IN7
P096_CommandTrigger_toString(P096_CommandTrigger::ws2in7)
# endif // if P096_USE_WAVESHARE_2IN7
};
const int commandTriggerOptions[] = {
static_cast<int>(P096_CommandTrigger::epd),
@@ -363,7 +374,10 @@ boolean Plugin_096(uint8_t function, struct EventStruct *event, String& string)
static_cast<int>(P096_CommandTrigger::ePaper),
static_cast<int>(P096_CommandTrigger::il3897),
static_cast<int>(P096_CommandTrigger::uc8151d),
static_cast<int>(P096_CommandTrigger::ssd1680)
static_cast<int>(P096_CommandTrigger::ssd1680),
# if P096_USE_WAVESHARE_2IN7
static_cast<int>(P096_CommandTrigger::ws2in7)
# endif // if P096_USE_WAVESHARE_2IN7
};
addFormSelector(F("Write Command trigger"),
F("p096_commandtrigger"),
@@ -556,296 +570,14 @@ boolean Plugin_096(uint8_t function, struct EventStruct *event, String& string)
case PLUGIN_WRITE:
{
# ifndef BUILD_NO_DEBUG
String tmpString = String(string);
# endif // ifndef BUILD_NO_DEBUG
String arguments = String(string);
P096_data_struct *P096_data = static_cast<P096_data_struct *>(getPluginTaskData(event->TaskIndex));
String command;
String subcommand;
int argIndex = arguments.indexOf(',');
if (argIndex)
{
command = arguments.substring(0, argIndex);
arguments = arguments.substring(argIndex + 1);
argIndex = arguments.indexOf(',');
subcommand = arguments.substring(0, argIndex);
success = true;
# ifndef BUILD_NO_DEBUG
tmpString += "<br/> command= " + command;
tmpString += "<br/> arguments= " + arguments;
tmpString += "<br/> argIndex= " + String(argIndex);
tmpString += "<br/> subcommand= " + subcommand;
# endif // ifndef BUILD_NO_DEBUG
// if (command.equalsIgnoreCase(F("EPDCMD")))
// {
// if (subcommand.equalsIgnoreCase(F("CLEAR")))
// {
// arguments = arguments.substring(argIndex + 1);
// eInkScreen->clearBuffer();
// eInkScreen->fillScreen(Plugin_096_ParseColor(arguments));
// eInkScreen->display();
// eInkScreen->clearBuffer();
// }
// else if (subcommand.equalsIgnoreCase(F("DEEPSLEEP")))
// {
// eInkScreen->deepSleep();
// }
// else if (subcommand.equalsIgnoreCase(F("SEQ_START")))
// {
// eInkScreen->clearBuffer();
// eInkScreen->fillScreen(Plugin_096_ParseColor(arguments));
// plugin_096_sequence_in_progress = true;
// }
// else if (subcommand.equalsIgnoreCase(F("SEQ_END")))
// {
// # ifndef BUILD_NO_DEBUG
// TimingStats s;
// const unsigned statisticsTimerStart(micros());
// # endif // ifndef BUILD_NO_DEBUG
// eInkScreen->display();
// # ifndef BUILD_NO_DEBUG
// s.add(usecPassedSince(statisticsTimerStart));
// tmpString += "<br/> Display timings = " + String(s.getAvg());
// # endif // ifndef BUILD_NO_DEBUG
// eInkScreen->clearBuffer();
// plugin_096_sequence_in_progress = false;
// }
// else if (subcommand.equalsIgnoreCase(F("INV")))
// {
// arguments = arguments.substring(argIndex + 1);
// eInkScreen->invertDisplay(arguments.toInt() == 1);
// eInkScreen->display();
// }
// else if (subcommand.equalsIgnoreCase(F("ROT")))
// {
// arguments = arguments.substring(argIndex + 1);
// eInkScreen->setRotation(arguments.toInt() % 4);
// eInkScreen->display();
// }
// else
// {
// success = false;
// }
// }
// else if (command.equalsIgnoreCase(F("EPD")))
// {
// # ifdef P096_USE_ADA_GRAPHICS
// String tmp = string;
// success = gfxHelper->processCommand(AdaGFXparseTemplate(tmp, PCONFIG(2) / 10)); // Hand it over after replacing
// variables
// # else // ifdef P096_USE_ADA_GRAPHICS
// # ifndef BUILD_NO_DEBUG
// tmpString += "<br/> EPD ";
// # endif // ifndef BUILD_NO_DEBUG
// arguments = arguments.substring(argIndex + 1);
// String sParams[8];
// int argCount = Plugin_096_StringSplit(arguments, ',', sParams, 8);
// # ifndef BUILD_NO_DEBUG
// for (int a = 0; a < argCount && a < 8; a++)
// {
// tmpString += "<br/> ARGS[" + String(a) + "]=" + sParams[a];
// }
// # endif // ifndef BUILD_NO_DEBUG
// if (plugin_096_sequence_in_progress == false)
// {
// eInkScreen->clearBuffer();
// eInkScreen->fillScreen(EPD_WHITE);
// }
// if (subcommand.equalsIgnoreCase(F("txt")))
// {
// Plugin_096_FixText(arguments);
// eInkScreen->println(arguments); // write all pending cars
// }
// else if (subcommand.equalsIgnoreCase(F("txz")))
// {
// eInkScreen->setCursor(sParams[0].toInt(), sParams[1].toInt());
// Plugin_096_FixText(sParams[2]);
// eInkScreen->println(sParams[2]); // write all pending cars
// }
// else if (subcommand.equalsIgnoreCase(F("txp")) && (argCount == 2))
// {
// eInkScreen->setCursor(sParams[0].toInt(), sParams[1].toInt());
// }
// else if (subcommand.equalsIgnoreCase(F("txc")) && ((argCount == 1) || (argCount == 2)))
// {
// if (argCount == 1) {
// eInkScreen->setTextColor(Plugin_096_ParseColor(sParams[0]));
// }
// else { // argCount=2
// eInkScreen->setTextColor(Plugin_096_ParseColor(sParams[0]), Plugin_096_ParseColor(sParams[1]));
// }
// }
// else if (subcommand.equalsIgnoreCase(F("txs")) && (argCount == 1))
// {
// eInkScreen->setTextSize(sParams[0].toInt());
// }
// else if (subcommand.equalsIgnoreCase(F("txtfull")) && (argCount >= 3) && (argCount <= 6))
// {
// switch (argCount)
// {
// case 3: // single text
// Plugin_096_printText(sParams[2].c_str(), sParams[0].toInt() - 1, sParams[1].toInt() - 1);
// break;
// case 4: // text + size
// Plugin_096_printText(sParams[3].c_str(), sParams[0].toInt() - 1, sParams[1].toInt() - 1, sParams[2].toInt());
// break;
// case 5: // text + size + color
// Plugin_096_printText(sParams[4].c_str(),
// sParams[0].toInt() - 1,
// sParams[1].toInt() - 1,
// sParams[2].toInt(),
// Plugin_096_ParseColor(sParams[3]));
// break;
// case 6: // text + size + color
// Plugin_096_printText(sParams[5].c_str(),
// sParams[0].toInt() - 1,
// sParams[1].toInt() - 1,
// sParams[2].toInt(),
// Plugin_096_ParseColor(sParams[3]),
// Plugin_096_ParseColor(sParams[4]));
// break;
// default:
// success = false;
// break;
// }
// }
// else if (subcommand.equalsIgnoreCase(F("l")) && (argCount == 5))
// {
// eInkScreen->drawLine(sParams[0].toInt(), sParams[1].toInt(), sParams[2].toInt(), sParams[3].toInt(),
// Plugin_096_ParseColor(sParams[4]));
// }
// else if (subcommand.equalsIgnoreCase(F("lh")) && (argCount == 3))
// {
// eInkScreen->drawFastHLine(0, sParams[0].toInt(), sParams[1].toInt(), Plugin_096_ParseColor(sParams[2]));
// }
// else if (subcommand.equalsIgnoreCase(F("lv")) && (argCount == 3))
// {
// eInkScreen->drawFastVLine(sParams[0].toInt(), 0, sParams[1].toInt(), Plugin_096_ParseColor(sParams[2]));
// }
// else if (subcommand.equalsIgnoreCase(F("r")) && (argCount == 5))
// {
// eInkScreen->drawRect(sParams[0].toInt(), sParams[1].toInt(), sParams[2].toInt(), sParams[3].toInt(),
// Plugin_096_ParseColor(sParams[4]));
// }
// else if (subcommand.equalsIgnoreCase(F("rf")) && (argCount == 6))
// {
// eInkScreen->fillRect(sParams[0].toInt(), sParams[1].toInt(), sParams[2].toInt(), sParams[3].toInt(),
// Plugin_096_ParseColor(sParams[5]));
// eInkScreen->drawRect(sParams[0].toInt(), sParams[1].toInt(), sParams[2].toInt(), sParams[3].toInt(),
// Plugin_096_ParseColor(sParams[4]));
// }
// else if (subcommand.equalsIgnoreCase(F("c")) && (argCount == 4))
// {
// eInkScreen->drawCircle(sParams[0].toInt(), sParams[1].toInt(), sParams[2].toInt(),
// Plugin_096_ParseColor(sParams[3]));
// }
// else if (subcommand.equalsIgnoreCase(F("cf")) && (argCount == 5))
// {
// eInkScreen->fillCircle(sParams[0].toInt(), sParams[1].toInt(), sParams[2].toInt(),
// Plugin_096_ParseColor(sParams[4]));
// eInkScreen->drawCircle(sParams[0].toInt(), sParams[1].toInt(), sParams[2].toInt(),
// Plugin_096_ParseColor(sParams[3]));
// }
// else if (subcommand.equalsIgnoreCase(F("t")) && (argCount == 7))
// {
// eInkScreen->drawTriangle(sParams[0].toInt(),
// sParams[1].toInt(),
// sParams[2].toInt(),
// sParams[3].toInt(),
// sParams[4].toInt(),
// sParams[5].toInt(),
// Plugin_096_ParseColor(sParams[6]));
// }
// else if (subcommand.equalsIgnoreCase(F("tf")) && (argCount == 8))
// {
// eInkScreen->fillTriangle(sParams[0].toInt(),
// sParams[1].toInt(),
// sParams[2].toInt(),
// sParams[3].toInt(),
// sParams[4].toInt(),
// sParams[5].toInt(),
// Plugin_096_ParseColor(sParams[7]));
// eInkScreen->drawTriangle(sParams[0].toInt(),
// sParams[1].toInt(),
// sParams[2].toInt(),
// sParams[3].toInt(),
// sParams[4].toInt(),
// sParams[5].toInt(),
// Plugin_096_ParseColor(sParams[6]));
// }
// else if (subcommand.equalsIgnoreCase(F("rr")) && (argCount == 6))
// {
// eInkScreen->drawRoundRect(sParams[0].toInt(),
// sParams[1].toInt(),
// sParams[2].toInt(),
// sParams[3].toInt(),
// sParams[4].toInt(),
// Plugin_096_ParseColor(sParams[5]));
// }
// else if (subcommand.equalsIgnoreCase(F("rrf")) && (argCount == 7))
// {
// eInkScreen->fillRoundRect(sParams[0].toInt(),
// sParams[1].toInt(),
// sParams[2].toInt(),
// sParams[3].toInt(),
// sParams[4].toInt(),
// Plugin_096_ParseColor(sParams[6]));
// eInkScreen->drawRoundRect(sParams[0].toInt(),
// sParams[1].toInt(),
// sParams[2].toInt(),
// sParams[3].toInt(),
// sParams[4].toInt(),
// Plugin_096_ParseColor(sParams[5]));
// }
// else if (subcommand.equalsIgnoreCase(F("px")) && (argCount == 3))
// {
// eInkScreen->drawPixel(sParams[0].toInt(), sParams[1].toInt(), Plugin_096_ParseColor(sParams[2]));
// }
// else
// {
// success = false;
// }
// # endif // ifdef P096_USE_ADA_GRAPHICS
// }
// else
// {
// success = false;
// }
if (nullptr != P096_data) {
success = P096_data->plugin_write(event, string); // Write operation, handle commands
}
else
{
// invalid arguments
success = false;
}
// in case of command outside of sequence, then refresh screen
// if (success && !plugin_096_sequence_in_progress)
// {
// eInkScreen->display();
// }
// # ifndef BUILD_NO_DEBUG
// String log;
// log.reserve(110); // Prevent re-allocation
// log = F("P096-eInk : WRITE = ");
// log += tmpString;
// SendStatus(event, log); // Reply (echo) to sender. This will print message on browser.
// # endif // ifndef BUILD_NO_DEBUG
break;
}
}
return success;
@@ -12,6 +12,9 @@ const __FlashStringHelper* EPD_type_toString(EPD_type_e 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_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;
}
return F("Unsupported type!");
@@ -27,6 +30,9 @@ const __FlashStringHelper* P096_CommandTrigger_toString(P096_CommandTrigger cmd)
case P096_CommandTrigger::il3897: return F("il3897");
case P096_CommandTrigger::uc8151d: return F("uc8151d");
case P096_CommandTrigger::ssd1680: return F("ssd1680");
# 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");
case P096_CommandTrigger::epd: break;
}
@@ -47,6 +53,12 @@ void EPD_type_toResolution(EPD_type_e device, uint16_t& x, uint16_t& y) {
x = 212;
y = 104;
break;
# if P096_USE_WAVESHARE_2IN7
case EPD_type_e::EPD_WS2IN7:
x = 264;
y = 176;
break;
# endif // if P096_USE_WAVESHARE_2IN7
case EPD_type_e::EPD_MAX:
break;
}
@@ -120,6 +132,11 @@ bool P096_data_struct::plugin_init(struct EventStruct *event) {
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;
# endif // if P096_USE_WAVESHARE_2IN7
case EPD_type_e::EPD_MAX:
break;
}
@@ -202,6 +219,7 @@ void P096_data_struct::updateFontMetrics() {
gfxHelper->getTextMetrics(_textcols, _textrows, _fontwidth, _fontheight, _fontscaling, _heightOffset, _xpix, _ypix);
gfxHelper->getColors(_fgcolor, _bgcolor);
} else {
if (_fontscaling == 0) { _fontscaling = 1; }
_textcols = _xpix / (_fontwidth * _fontscaling);
_textrows = _ypix / (_fontheight * _fontscaling);
}
+23 -13
View File
@@ -4,15 +4,19 @@
#include "../../_Plugin_Helper.h"
#ifdef USES_P096
# include <Adafruit_GFX.h> // include Adafruit graphics library
# include <LOLIN_EPD.h> // include Adafruit Lolin eInk/ePaper library
# include <Adafruit_GFX.h> // include Adafruit graphics library
# include <LOLIN_EPD.h> // 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
# include "../CustomBuild/StorageLayout.h"
@@ -64,19 +68,25 @@
# endif // ifdef ESP32
enum class EPD_type_e : uint8_t {
EPD_IL3897 = 0,
EPD_UC8151D,
EPD_SSD1680,
EPD_IL3897 = 0u,
EPD_UC8151D = 1u,
EPD_SSD1680 = 2u,
# if P096_USE_WAVESHARE_2IN7
EPD_WS2IN7 = 3u,
# endif // if P096_USE_WAVESHARE_2IN7
EPD_MAX // must be last value in enum
};
enum class P096_CommandTrigger : uint8_t {
epd = 0u,
eInk,
ePaper,
il3897,
uc8151d,
ssd1680,
epd = 0u,
eInk = 1u,
ePaper = 2u,
il3897 = 3u,
uc8151d = 4u,
ssd1680 = 5u,
# if P096_USE_WAVESHARE_2IN7
ws2in7 = 6u,
# endif // if P096_USE_WAVESHARE_2IN7
MAX // Keep as last item!
};