Files
ESPEasy/lib/LOLIN_EPD/src/Waveshare_2in7.cpp
T

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,
};