mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-09-14 18:46:59 +00:00
511 lines
12 KiB
C++
511 lines
12 KiB
C++
#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 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_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);
|
|
}
|
|
|
|
/**************************************************************************/
|
|
|
|
/*!
|
|
@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(WS2IN7_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(WS2IN7_BOOSTER_SOFT_START);
|
|
sendData(0x07);
|
|
sendData(0x07);
|
|
sendData(0x17);
|
|
|
|
// Power optimization
|
|
sendCmd(WS2IN7_POWER_OPTIMIZATION);
|
|
sendData(0x60);
|
|
sendData(0xA5);
|
|
|
|
// Power optimization
|
|
sendCmd(WS2IN7_POWER_OPTIMIZATION);
|
|
sendData(0x89);
|
|
sendData(0xA5);
|
|
|
|
// Power optimization
|
|
sendCmd(WS2IN7_POWER_OPTIMIZATION);
|
|
sendData(0x90);
|
|
sendData(0x00);
|
|
|
|
// Power optimization
|
|
sendCmd(WS2IN7_POWER_OPTIMIZATION);
|
|
sendData(0x93);
|
|
sendData(0x2A);
|
|
|
|
// Power optimization
|
|
sendCmd(WS2IN7_POWER_OPTIMIZATION);
|
|
sendData(0xA0);
|
|
sendData(0xA5);
|
|
|
|
// Power optimization
|
|
sendCmd(WS2IN7_POWER_OPTIMIZATION);
|
|
sendData(0xA1);
|
|
sendData(0x00);
|
|
|
|
// Power optimization
|
|
sendCmd(WS2IN7_POWER_OPTIMIZATION);
|
|
sendData(0x73);
|
|
sendData(0x41);
|
|
|
|
sendCmd(WS2IN7_PARTIAL_DISPLAY_REFRESH);
|
|
sendData(0x00);
|
|
sendCmd(WS2IN7_POWER_ON);
|
|
readBusy();
|
|
|
|
sendCmd(WS2IN7_PANEL_SETTING);
|
|
sendData(0xAF); // KW-BF KWR-AF BWROTP 0f
|
|
sendCmd(WS2IN7_PLL_CONTROL);
|
|
sendData(0x3A); // 3A 100HZ 29 150Hz 39 200HZ 31 171HZ
|
|
sendCmd(WS2IN7_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(WS2IN7_LUT_FOR_VCOM); // vcom
|
|
|
|
for (count = 0; count < 44; count++) {
|
|
sendData(lut_vcom_dc[count]);
|
|
}
|
|
|
|
sendCmd(WS2IN7_LUT_WHITE_TO_WHITE); // ww --
|
|
|
|
for (count = 0; count < 42; count++) {
|
|
sendData(lut_ww[count]);
|
|
}
|
|
|
|
sendCmd(WS2IN7_LUT_BLACK_TO_WHITE); // bw r
|
|
|
|
for (count = 0; count < 42; count++) {
|
|
sendData(lut_bw[count]);
|
|
}
|
|
|
|
sendCmd(WS2IN7_LUT_WHITE_TO_BLACK); // wb w
|
|
|
|
for (count = 0; count < 42; count++) {
|
|
sendData(lut_bb[count]);
|
|
}
|
|
|
|
sendCmd(WS2IN7_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(WS2IN7_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(WS2IN7_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;
|
|
|
|
// Transformed to native pixels
|
|
if ((x < 0) || (x >= width()) || (y < 0) || (y >= height())) {
|
|
return;
|
|
}
|
|
|
|
// Corrections by @kretzp (Peter Kretz) 2022-03-27
|
|
// 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() + 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(WS2IN7_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,
|
|
};
|