mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-09-14 10:35:30 +00:00
271 lines
6.2 KiB
C++
271 lines
6.2 KiB
C++
#include "LOLIN_EPD.h"
|
|
#include "LOLIN_SSD1680.h"
|
|
|
|
#define ALLSCREEN_GRAGHBYTES 4000
|
|
|
|
///////////////////////////////////////////////////
|
|
|
|
/////////////////EPD settings Functions/////////////////////
|
|
|
|
#define BUSY_WAIT 500
|
|
|
|
/*!
|
|
@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
|
|
*/
|
|
/**************************************************************************/
|
|
LOLIN_SSD1680::LOLIN_SSD1680(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_buf = (uint8_t *)malloc(width * _height_8bit / 8);
|
|
red_buf = (uint8_t *)malloc(width * _height_8bit / 8);
|
|
bw_bufsize = width * _height_8bit / 8;
|
|
red_bufsize = bw_bufsize;
|
|
}
|
|
|
|
LOLIN_SSD1680::LOLIN_SSD1680(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_buf = (uint8_t *)malloc(width * _height_8bit / 8);
|
|
red_buf = (uint8_t *)malloc(width * _height_8bit / 8);
|
|
bw_bufsize = 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 LOLIN_SSD1680::begin(bool reset)
|
|
{
|
|
// uint8_t HRES = 0x68; //104
|
|
// uint8_t VRES_byte1 = 0x00; //212
|
|
// uint8_t VRES_byte2 = 0xd4;
|
|
|
|
// uint8_t buf[5];
|
|
LOLIN_EPD::begin(reset);
|
|
|
|
readBusy();
|
|
sendCmd(0x12); //SWRESET
|
|
readBusy();
|
|
|
|
sendCmd(0x01); //Driver output control
|
|
sendData(0xF9);
|
|
sendData(0x00);
|
|
sendData(0x00);
|
|
|
|
sendCmd(0x11); //data entry mode
|
|
sendData(0x01);
|
|
|
|
sendCmd(0x44); //set Ram-X address start/end position
|
|
sendData(0x00);
|
|
sendData(0x0F); //0x0F-->(15+1)*8=128
|
|
|
|
sendCmd(0x45); //set Ram-Y address start/end position
|
|
sendData(0xF9); //0xF9-->(249+1)=250
|
|
sendData(0x00);
|
|
sendData(0x00);
|
|
sendData(0x00);
|
|
|
|
sendCmd(0x3C); //BorderWavefrom
|
|
sendData(0x05);
|
|
|
|
sendCmd(0x18); //Read built-in temperature sensor
|
|
sendData(0x80);
|
|
|
|
sendCmd(0x21); // Display update control
|
|
sendData(0x00);
|
|
sendData(0x80);
|
|
|
|
sendCmd(0x4E); // set RAM x address count to 0;
|
|
sendData(0x00);
|
|
sendCmd(0x4F); // set RAM y address count to 0X199;
|
|
sendData(0xF9);
|
|
sendData(0x00);
|
|
readBusy();
|
|
|
|
// sendData(HEIGHT);
|
|
// sendData((WIDTH >> 8) & 0xff);
|
|
// sendData(WIDTH & 0xff);
|
|
}
|
|
|
|
void LOLIN_SSD1680::display()
|
|
{
|
|
|
|
sendCmd(0x24); //write RAM for black(0)/white (1)
|
|
|
|
for (uint16_t i = 0; i < bw_bufsize; i++)
|
|
{
|
|
sendData(bw_buf[i]);
|
|
}
|
|
|
|
sendCmd(0x26); //write RAM for red(1)/white (0)
|
|
|
|
for (uint16_t i = 0; i < red_bufsize; i++)
|
|
{
|
|
sendData(red_buf[i]);
|
|
}
|
|
|
|
update();
|
|
}
|
|
void LOLIN_SSD1680::update()
|
|
{
|
|
sendCmd(0x22); //Display Update Control
|
|
sendData(0xF7);
|
|
sendCmd(0x20); //Activate Display Update Sequence
|
|
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 LOLIN_SSD1680::drawPixel(int16_t x, int16_t y, uint16_t color)
|
|
{
|
|
if ((x < 0) || (x >= width()) || (y < 0) || (y >= height()))
|
|
return;
|
|
|
|
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;
|
|
}
|
|
//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 |= (1 << (7 - y % 8));
|
|
break;
|
|
case EPD_RED:
|
|
*pBuf |= (1 << (7 - y % 8));
|
|
break;
|
|
case EPD_BLACK:
|
|
*pBuf &= ~(1 << (7 - y % 8));
|
|
break;
|
|
case EPD_INVERSE:
|
|
*pBuf ^= (1 << (7 - y % 8));
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief clear all data buffers
|
|
*/
|
|
/**************************************************************************/
|
|
void LOLIN_SSD1680::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 LOLIN_SSD1680::clearDisplay()
|
|
{
|
|
clearBuffer();
|
|
display();
|
|
delay(100);
|
|
display();
|
|
}
|
|
|
|
void LOLIN_SSD1680::readBusy()
|
|
{
|
|
if (busy >= 0)
|
|
{
|
|
while (1)
|
|
{
|
|
if (digitalRead(busy) == 0)
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
delay(BUSY_WAIT);
|
|
}
|
|
}
|
|
|
|
void LOLIN_SSD1680::deepSleep()
|
|
{
|
|
|
|
sendCmd(0x10); //enter deep sleep
|
|
sendData(0x01);
|
|
delay(100);
|
|
}
|
|
|
|
void LOLIN_SSD1680::fillbuffer(const unsigned char *black_image, const unsigned char *red_image)
|
|
{
|
|
for (int i = 0; i < bw_bufsize; i++)
|
|
{
|
|
bw_buf[i] = pgm_read_byte(&black_image[i]);
|
|
}
|
|
|
|
for (int i = 0; i < red_bufsize; i++)
|
|
{
|
|
red_buf[i] = pgm_read_byte(&red_image[i]);
|
|
}
|
|
}
|