mirror of
https://github.com/WeActStudio/WeActStudio.EpaperModule.git
synced 2026-08-16 13:13:45 +02:00
1194 lines
24 KiB
C
1194 lines
24 KiB
C
/*---------------------------------------
|
|
- WeAct Studio Official Link
|
|
- taobao: weactstudio.taobao.com
|
|
- aliexpress: weactstudio.aliexpress.com
|
|
- github: github.com/WeActTC
|
|
- gitee: gitee.com/WeAct-TC
|
|
- blog: www.weact-tc.cn
|
|
---------------------------------------*/
|
|
|
|
#include "epaper.h"
|
|
#include "epdfont.h"
|
|
|
|
#include <wiringPi.h>
|
|
#include <wiringPiSPI.h>
|
|
|
|
// epaper module
|
|
// res pin -> Pin 11
|
|
// busy pin -> Pin 18
|
|
// d/c pin -> Pin 22
|
|
// cs pin -> Pin 24
|
|
// sck/scl pin -> Pin 23
|
|
// mosi/sda pin -> Pin 19
|
|
|
|
#define RES_PIN 17 // Pin 11
|
|
#define DC_PIN 25 // Pin 22
|
|
#define CS_PIN 8 // Pin 14
|
|
#define BUSY_PIN 24 // Pin 18
|
|
#define SPI_CHANNEL 0 // SPI Channel
|
|
|
|
uint16_t EPD_H;
|
|
uint16_t EPD_W;
|
|
|
|
EPD_PAINT EPD_Paint;
|
|
|
|
uint8_t epd_type = 0;
|
|
|
|
static uint8_t _hibernating = 1;
|
|
|
|
static uint8_t old_data[30 * 416] = {0};
|
|
|
|
static const unsigned char lut_partial[] =
|
|
{
|
|
0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80,0x80,0x0,0x0,0x0,0x0,0x0,0x0,
|
|
0x0,0x0,0x0,0x0,0x40,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80,0x0,0x0,
|
|
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0A,
|
|
0x0,0x0,0x0,0x0,0x0,0x2,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
|
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
|
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
|
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x22,
|
|
0x22,0x22,0x22,0x22,0x22,0x0,0x0,0x0,
|
|
};
|
|
|
|
void epd_delay(uint16_t ms)
|
|
{
|
|
delay(ms);
|
|
}
|
|
|
|
// 修改GPIO控制函数
|
|
void epd_res_set()
|
|
{
|
|
digitalWrite(RES_PIN, HIGH);
|
|
}
|
|
|
|
void epd_res_reset()
|
|
{
|
|
digitalWrite(RES_PIN, LOW);
|
|
}
|
|
|
|
void epd_dc_set()
|
|
{
|
|
digitalWrite(DC_PIN, HIGH);
|
|
}
|
|
|
|
void epd_dc_reset()
|
|
{
|
|
digitalWrite(DC_PIN, LOW);
|
|
}
|
|
|
|
void epd_cs_set()
|
|
{
|
|
// digitalWrite(CS_PIN, HIGH);
|
|
}
|
|
|
|
void epd_cs_reset()
|
|
{
|
|
// digitalWrite(CS_PIN, LOW);
|
|
}
|
|
|
|
uint8_t epd_is_busy()
|
|
{
|
|
if (epd_type == EPD370_UC8253)
|
|
{
|
|
return digitalRead(BUSY_PIN) ? 0 : 1;
|
|
}
|
|
else
|
|
{
|
|
return digitalRead(BUSY_PIN) ? 1 : 0;
|
|
}
|
|
}
|
|
|
|
void epd_io_init(void)
|
|
{
|
|
// wiringPiSetup();
|
|
if (wiringPiSetupGpio() < 0)
|
|
{ // use BCM2835 Pin number table
|
|
printf("set wiringPi lib failed!\r\n");
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
printf("set wiringPi lib success!\r\n");
|
|
}
|
|
|
|
int mode = epd_type == EPD370_UC8253 ? 0 : 3;
|
|
if (wiringPiSPISetupMode(SPI_CHANNEL, 1000000, mode) < 0)
|
|
{
|
|
printf("spi setup failed!\r\n");
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
printf("spi setup success!\r\n");
|
|
}
|
|
|
|
// epd_cs_set();
|
|
epd_dc_set();
|
|
epd_res_set();
|
|
|
|
pinMode(RES_PIN, OUTPUT);
|
|
pinMode(DC_PIN, OUTPUT);
|
|
// pinMode(CS_PIN, OUTPUT);
|
|
pinMode(BUSY_PIN, INPUT);
|
|
}
|
|
|
|
void epd_io_deinit(void)
|
|
{
|
|
pinMode(RES_PIN, PM_OFF);
|
|
pinMode(DC_PIN, PM_OFF);
|
|
// pinMode(CS_PIN, PM_OFF);
|
|
pinMode(BUSY_PIN, PM_OFF);
|
|
wiringPiSPIClose(SPI_CHANNEL);
|
|
}
|
|
|
|
// 修改SPI数据传输函数
|
|
void epd_write_reg(uint8_t reg)
|
|
{
|
|
epd_dc_reset();
|
|
epd_cs_reset();
|
|
|
|
wiringPiSPIDataRW(SPI_CHANNEL, ®, 1);
|
|
|
|
epd_cs_set();
|
|
epd_dc_set();
|
|
}
|
|
|
|
void epd_write_data(uint8_t data)
|
|
{
|
|
epd_cs_reset();
|
|
|
|
wiringPiSPIDataRW(SPI_CHANNEL, &data, 1);
|
|
|
|
epd_cs_set();
|
|
}
|
|
|
|
void _epd_write_data(uint8_t *data, uint32_t len)
|
|
{
|
|
uint8_t *dummy = malloc(len);
|
|
memcpy(dummy, data, len);
|
|
if(dummy) {
|
|
uint32_t chunk_size = 4096;
|
|
if(chunk_size == 0 || chunk_size > len) {
|
|
chunk_size = len; // 如果块大小为0或大于总长度,则一次性传输
|
|
}
|
|
|
|
uint32_t remaining = len;
|
|
uint32_t offset = 0;
|
|
|
|
while(remaining > 0) {
|
|
uint32_t current_chunk = (remaining > chunk_size) ? chunk_size : remaining;
|
|
wiringPiSPIDataRW(SPI_CHANNEL, dummy + offset, current_chunk);
|
|
offset += current_chunk;
|
|
remaining -= current_chunk;
|
|
}
|
|
|
|
free(dummy);
|
|
}
|
|
}
|
|
|
|
uint8_t epd_wait_busy()
|
|
{
|
|
uint32_t timeout = 0;
|
|
while (epd_is_busy())
|
|
{
|
|
timeout++;
|
|
if (timeout > 40000)
|
|
{
|
|
return 1;
|
|
}
|
|
epd_delay(1);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void epd_reset(void)
|
|
{
|
|
epd_res_reset();
|
|
epd_delay(50);
|
|
epd_res_set();
|
|
epd_delay(50);
|
|
_hibernating = 0;
|
|
}
|
|
|
|
void epd_set_panel(uint8_t type, uint16_t width, uint16_t height)
|
|
{
|
|
epd_type = type;
|
|
EPD_H = height;
|
|
EPD_W = width;
|
|
|
|
printf("EPD_H: %d, EPD_W: %d, epd_type: %d\n", EPD_H, EPD_W, epd_type);
|
|
}
|
|
|
|
uint8_t epd_init(void)
|
|
{
|
|
if (_hibernating)
|
|
epd_reset();
|
|
|
|
if (epd_wait_busy())
|
|
return 1;
|
|
|
|
if (epd_type == EPD370_UC8253)
|
|
{
|
|
epd_write_reg(0x04);
|
|
|
|
if (epd_wait_busy())
|
|
return 1;
|
|
|
|
epd_write_reg(0x00);
|
|
epd_write_data(0x1F);
|
|
epd_write_data(0x0D);
|
|
|
|
epd_write_reg(0x50); // VCOM AND DATA INTERVAL SETTING
|
|
epd_write_data(0x97); // WBmode:VBDF 17|D7 VBDW 97 VBDB 57
|
|
return 0;
|
|
}
|
|
|
|
epd_write_reg(0x12); // SWRESET
|
|
|
|
epd_delay(100);
|
|
|
|
if (epd_wait_busy())
|
|
return 1;
|
|
|
|
if (epd_type == EPD213_219 || epd_type == EPD154)
|
|
{
|
|
epd_write_reg(0x01); // Driver output control
|
|
if (epd_type == EPD213_219)
|
|
{
|
|
epd_write_data(0x27);
|
|
epd_write_data(0x01);
|
|
epd_write_data(0x01);
|
|
}
|
|
else
|
|
{
|
|
epd_write_data(0xC7);
|
|
epd_write_data(0x00);
|
|
epd_write_data(0x01);
|
|
}
|
|
|
|
epd_write_reg(0x11); // data entry mode
|
|
epd_write_data(0x01);
|
|
|
|
if (epd_type == EPD154)
|
|
{
|
|
epd_write_reg(0x44); // set Ram-X address start/end position
|
|
epd_write_data(0x00);
|
|
epd_write_data(0x18);
|
|
|
|
epd_write_reg(0x45); // set Ram-Y address start/end position
|
|
epd_write_data(0xC7);
|
|
epd_write_data(0x00);
|
|
epd_write_data(0x00);
|
|
epd_write_data(0x00);
|
|
}
|
|
else
|
|
{
|
|
epd_write_reg(0x44); // set Ram-X address start/end position
|
|
epd_write_data(0x00);
|
|
epd_write_data(0x0F); // 0x0F-->(15+1)*8=128
|
|
|
|
epd_write_reg(0x45); // set Ram-Y address start/end position
|
|
epd_write_data(0x27); // 0x127-->(295+1)=296
|
|
epd_write_data(0x01);
|
|
epd_write_data(0x00);
|
|
epd_write_data(0x00);
|
|
}
|
|
|
|
epd_write_reg(0x3C); // BorderWavefrom
|
|
epd_write_data(0x05);
|
|
|
|
if (epd_type == EPD213_219)
|
|
{
|
|
epd_write_reg(0x21); // Display update control
|
|
epd_write_data(0x00);
|
|
epd_write_data(0x80);
|
|
}
|
|
}
|
|
else if (epd_type == EPD420)
|
|
{
|
|
epd_write_reg(0x21); // Display Update Controll
|
|
epd_write_data(0x40);
|
|
epd_write_data(0x00);
|
|
epd_write_reg(0x01); // Set MUX as 300
|
|
epd_write_data(0x2B);
|
|
epd_write_data(0x01);
|
|
epd_write_data(0x00);
|
|
epd_write_reg(0x3C); // BorderWavefrom
|
|
epd_write_data(0x01);
|
|
epd_write_reg(0x11); // data entry mode
|
|
epd_write_data(0x03); // X-mode
|
|
epd_address_set(0, 0, EPD_W - 1, EPD_H - 1);
|
|
}
|
|
|
|
epd_write_reg(0x18); // Read built-in temperature sensor
|
|
epd_write_data(0x80);
|
|
|
|
epd_setpos(0, 0);
|
|
|
|
if (epd_power_on())
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint8_t epd_init_fast(void)
|
|
{
|
|
if (epd_init())
|
|
return 1;
|
|
|
|
if (epd_type == EPD370_UC8253)
|
|
{
|
|
epd_write_reg(0xE0);
|
|
epd_write_data(0x02);
|
|
|
|
epd_write_reg(0xE5);
|
|
epd_write_data(0x5F); //0x5F--1.5s
|
|
}
|
|
else
|
|
{
|
|
epd_write_reg(0x22); // Load temperature value
|
|
epd_write_data(0xB1);
|
|
epd_write_reg(0x20);
|
|
if (epd_wait_busy())
|
|
return 1;
|
|
|
|
epd_write_reg(0x1A); // Write to temperature register
|
|
epd_write_data(0x6E);
|
|
|
|
epd_write_reg(0x22); // Load temperature value
|
|
epd_write_data(0x91);
|
|
epd_write_reg(0x20);
|
|
if (epd_wait_busy())
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint8_t epd_init_partial(void)
|
|
{
|
|
if (epd_init())
|
|
return 1;
|
|
|
|
if (epd_type == EPD213_219)
|
|
{
|
|
epd_write_reg(0x32);
|
|
epd_cs_reset();
|
|
_epd_write_data((uint8_t *)&lut_partial, sizeof(lut_partial));
|
|
epd_cs_set();
|
|
}
|
|
else if (epd_type == EPD420)
|
|
{
|
|
epd_write_reg(0x3C); // BorderWavefrom
|
|
epd_write_data(0x80);
|
|
epd_write_reg(0x21); // Display Update Controll
|
|
epd_write_data(0x00); // RED normal
|
|
epd_write_data(0x00); // single chip application
|
|
}
|
|
else if (epd_type == EPD370_UC8253)
|
|
{
|
|
epd_write_reg(0xE0);
|
|
epd_write_data(0x02);
|
|
|
|
epd_write_reg(0xE5);
|
|
epd_write_data(0x6E);
|
|
|
|
epd_write_reg(0x50);
|
|
epd_write_data(0xD7);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void epd_enter_deepsleepmode(uint8_t mode)
|
|
{
|
|
epd_power_off();
|
|
if (epd_type == EPD370_UC8253)
|
|
{
|
|
epd_write_reg(0X07); // deep sleep
|
|
epd_write_data(0xA5);
|
|
}
|
|
else
|
|
{
|
|
epd_write_reg(0x10);
|
|
epd_write_data(mode);
|
|
}
|
|
|
|
_hibernating = 1;
|
|
}
|
|
|
|
uint8_t epd_power_on(void)
|
|
{
|
|
if (epd_type == EPD370_UC8253)
|
|
{
|
|
epd_write_reg(0x04);
|
|
return epd_wait_busy();
|
|
}
|
|
else if (epd_type == EPD420)
|
|
{
|
|
epd_write_reg(0x22); // Display Update Control
|
|
epd_write_data(0xe0);
|
|
}
|
|
else
|
|
{
|
|
epd_write_reg(0x22); // Display Update Control
|
|
epd_write_data(0xf8);
|
|
}
|
|
epd_write_reg(0x20); // Activate Display Update Sequence
|
|
|
|
return epd_wait_busy();
|
|
}
|
|
|
|
uint8_t epd_power_off(void)
|
|
{
|
|
if (epd_type == EPD370_UC8253)
|
|
{
|
|
epd_write_reg(0x02);
|
|
}
|
|
else
|
|
{
|
|
epd_write_reg(0x22); // Display Update Control
|
|
epd_write_data(0x83);
|
|
epd_write_reg(0x20); // Activate Display Update Sequence
|
|
}
|
|
|
|
return epd_wait_busy();
|
|
}
|
|
|
|
void epd_init_internalTempSensor(void)
|
|
{
|
|
if (epd_type != EPD370_UC8253)
|
|
{
|
|
epd_write_reg(0x18);
|
|
epd_write_data(0x80);
|
|
|
|
epd_write_reg(0x1A);
|
|
epd_write_data(0x7F);
|
|
// epd_write_data(0xF0);
|
|
}
|
|
}
|
|
|
|
void epd_update(void)
|
|
{
|
|
if (epd_type == EPD370_UC8253)
|
|
{
|
|
epd_write_reg(0x12);
|
|
epd_delay(1);
|
|
epd_wait_busy();
|
|
return;
|
|
}
|
|
else if (epd_type == EPD154)
|
|
{
|
|
epd_write_reg(0x22); // Display Update Control
|
|
epd_write_data(0xF4);
|
|
}
|
|
else if (epd_type == EPD420)
|
|
{
|
|
epd_write_reg(0x22); // Display Update Control
|
|
epd_write_data(0xF7);
|
|
}
|
|
else
|
|
{
|
|
epd_write_reg(0x22); // Display Update Control
|
|
epd_write_data(0xF7);
|
|
}
|
|
epd_write_reg(0x20); // Activate Display Update Sequence
|
|
|
|
epd_wait_busy();
|
|
}
|
|
|
|
void epd_update_fast(void)
|
|
{
|
|
if (epd_type == EPD370_UC8253)
|
|
{
|
|
epd_update();
|
|
return;
|
|
}
|
|
else{
|
|
epd_write_reg(0x22); // Display Update Control
|
|
epd_write_data(0xC7);
|
|
}
|
|
epd_write_reg(0x20); // Activate Display Update Sequence
|
|
|
|
epd_wait_busy();
|
|
}
|
|
|
|
void epd_update_partial(void)
|
|
{
|
|
if (epd_type == EPD370_UC8253)
|
|
{
|
|
epd_update();
|
|
return;
|
|
}
|
|
else if (epd_type == EPD154)
|
|
{
|
|
epd_write_reg(0x22); // Display Update Control
|
|
epd_write_data(0xFC);
|
|
}
|
|
else if (epd_type == EPD420)
|
|
{
|
|
epd_write_reg(0x22); // Display Update Control
|
|
epd_write_data(0xFF);
|
|
}
|
|
else
|
|
{
|
|
epd_write_reg(0x22); // Display Update Control
|
|
epd_write_data(0xCC);
|
|
}
|
|
epd_write_reg(0x20); // Activate Display Update Sequence
|
|
|
|
epd_wait_busy();
|
|
}
|
|
|
|
void epd_address_set(uint16_t x_start, uint16_t y_start, uint16_t x_end, uint16_t y_end)
|
|
{
|
|
if (epd_type == EPD370_UC8253)
|
|
{
|
|
epd_write_reg(0x90); // SET_RAM_X_ADDRESS_START_END_POSITION
|
|
epd_write_data((x_start >> 3) & 0xFF);
|
|
epd_write_data((x_end >> 3) & 0xFF);
|
|
epd_write_data(y_start & 0xFF);
|
|
epd_write_data((y_start >> 8) & 0xFF);
|
|
epd_write_data(y_end & 0xFF);
|
|
epd_write_data((y_end >> 8) & 0xFF);
|
|
epd_write_data(0x01);
|
|
}
|
|
else
|
|
{
|
|
epd_write_reg(0x44); // SET_RAM_X_ADDRESS_START_END_POSITION
|
|
epd_write_data((x_start >> 3) & 0xFF);
|
|
epd_write_data((x_end >> 3) & 0xFF);
|
|
|
|
epd_write_reg(0x45); // SET_RAM_Y_ADDRESS_START_END_POSITION
|
|
epd_write_data(y_start & 0xFF);
|
|
epd_write_data((y_start >> 8) & 0xFF);
|
|
epd_write_data(y_end & 0xFF);
|
|
epd_write_data((y_end >> 8) & 0xFF);
|
|
}
|
|
}
|
|
|
|
void epd_setpos(uint16_t x, uint16_t y)
|
|
{
|
|
uint8_t _x;
|
|
uint16_t _y = 0;
|
|
|
|
_x = x / 8;
|
|
|
|
if (epd_type == EPD154)
|
|
_y = 199 - y;
|
|
else if (epd_type == EPD213_219)
|
|
_y = 295 - y;
|
|
else if (epd_type == EPD420)
|
|
_y = y;
|
|
else if (epd_type == EPD370_UC8253)
|
|
_y = y;
|
|
|
|
if (epd_type == EPD370_UC8253)
|
|
{
|
|
epd_write_reg(0x65);
|
|
epd_write_data(_x);
|
|
epd_write_data(_y >> 8 & 0x01);
|
|
epd_write_data(_y & 0xff);
|
|
}
|
|
else
|
|
{
|
|
epd_write_reg(0x4E); // set RAM x address count to 0;
|
|
epd_write_data(_x);
|
|
epd_write_reg(0x4F); // set RAM y address count to 0x127;
|
|
epd_write_data(_y & 0xff);
|
|
epd_write_data(_y >> 8 & 0x01);
|
|
}
|
|
}
|
|
|
|
void epd_write_imagedata(uint8_t *Image1, uint32_t length)
|
|
{
|
|
epd_cs_reset();
|
|
_epd_write_data(Image1,length);
|
|
epd_cs_set();
|
|
}
|
|
|
|
void epd_write_imagedata_invert(uint8_t *Image1, uint32_t length)
|
|
{
|
|
uint8_t *dummy = malloc(length);
|
|
for (uint32_t j = 0; j < length; j++)
|
|
{
|
|
dummy[j] = ~Image1[j];
|
|
}
|
|
|
|
epd_cs_reset();
|
|
_epd_write_data(dummy, length);
|
|
epd_cs_set();
|
|
|
|
free(dummy);
|
|
}
|
|
|
|
void epd_write_imagedata2(uint8_t data, uint32_t length)
|
|
{
|
|
uint8_t *dummy = malloc(length);
|
|
memset(dummy, data, length);
|
|
|
|
epd_cs_reset();
|
|
_epd_write_data(dummy, length);
|
|
epd_cs_set();
|
|
|
|
free(dummy);
|
|
}
|
|
|
|
void epd_display(uint8_t *Image1, uint8_t *Image2)
|
|
{
|
|
if (epd_type == EPD370_UC8253)
|
|
{
|
|
return;
|
|
}
|
|
|
|
uint32_t Width, Height;
|
|
uint32_t length;
|
|
Width = EPD_H;
|
|
Height = EPD_W_BUFF_SIZE;
|
|
length = Width * Height;
|
|
|
|
epd_setpos(0, 0);
|
|
|
|
epd_write_reg(0x24);
|
|
epd_write_imagedata(Image1, length);
|
|
|
|
epd_setpos(0, 0);
|
|
|
|
epd_write_reg(0x26);
|
|
epd_write_imagedata_invert(Image2, length);
|
|
|
|
if (epd_type == EPD420)
|
|
{
|
|
epd_write_reg(0x21); // Display Update Controll
|
|
epd_write_data(0x00); // RED normal
|
|
epd_write_data(0x00); // single chip application
|
|
}
|
|
|
|
epd_update();
|
|
}
|
|
|
|
void epd_displayBW(uint8_t *Image)
|
|
{
|
|
uint32_t Width, Height;
|
|
|
|
Width = EPD_H;
|
|
Height = EPD_W_BUFF_SIZE;
|
|
uint32_t length = Width * Height;
|
|
|
|
if (epd_type == EPD370_UC8253)
|
|
{
|
|
// epd_address_set(0, 0, EPD_W - 1, EPD_H - 1);
|
|
|
|
epd_write_reg(0x10);
|
|
epd_write_imagedata(old_data, length);
|
|
|
|
epd_write_reg(0x13);
|
|
epd_write_imagedata(Image, length);
|
|
memcpy(old_data, Image, length);
|
|
|
|
epd_update();
|
|
return;
|
|
}
|
|
|
|
epd_setpos(0, 0);
|
|
epd_write_reg(0x26);
|
|
epd_write_imagedata(Image, length);
|
|
|
|
epd_setpos(0, 0);
|
|
epd_write_reg(0x24);
|
|
epd_write_imagedata(Image, length);
|
|
|
|
epd_update();
|
|
}
|
|
|
|
void epd_displayBW_fast(uint8_t *Image)
|
|
{
|
|
uint32_t Width, Height;
|
|
|
|
Width = EPD_H;
|
|
Height = EPD_W_BUFF_SIZE;
|
|
uint32_t length = Width * Height;
|
|
|
|
if (epd_type == EPD370_UC8253)
|
|
{
|
|
// epd_address_set(0, 0, EPD_W - 1, EPD_H - 1);
|
|
|
|
epd_write_reg(0x10);
|
|
epd_write_imagedata(old_data, length);
|
|
|
|
epd_write_reg(0x13);
|
|
epd_write_imagedata(Image, length);
|
|
memcpy(old_data, Image, length);
|
|
|
|
epd_update();
|
|
return;
|
|
}
|
|
|
|
epd_setpos(0, 0);
|
|
epd_write_reg(0x26);
|
|
epd_write_imagedata(Image, length);
|
|
|
|
epd_setpos(0, 0);
|
|
epd_write_reg(0x24);
|
|
epd_write_imagedata(Image, length);
|
|
|
|
epd_update_fast();
|
|
}
|
|
|
|
void epd_displayBW_partial(uint8_t *Image)
|
|
{
|
|
|
|
if (epd_type == EPD370_UC8253)
|
|
{
|
|
epd_displayBW(Image);
|
|
return;
|
|
}
|
|
|
|
uint32_t Width, Height;
|
|
|
|
Width = EPD_H;
|
|
Height = EPD_W_BUFF_SIZE;
|
|
|
|
epd_setpos(0, 0);
|
|
epd_write_reg(0x24);
|
|
epd_write_imagedata(Image, Width * Height);
|
|
|
|
epd_update_partial();
|
|
|
|
epd_setpos(0, 0);
|
|
epd_write_reg(0x26);
|
|
epd_write_imagedata(Image, Width * Height);
|
|
}
|
|
|
|
void epd_displayRED(uint8_t *Image)
|
|
{
|
|
uint32_t Width, Height;
|
|
|
|
Width = EPD_H;
|
|
Height = EPD_W_BUFF_SIZE;
|
|
|
|
epd_setpos(0, 0);
|
|
|
|
epd_write_reg(0x26);
|
|
epd_write_imagedata(Image, Width * Height);
|
|
|
|
if (epd_type == EPD420)
|
|
{
|
|
epd_write_reg(0x21); // Display Update Controll
|
|
epd_write_data(0x00); // RED normal
|
|
epd_write_data(0x00); // single chip application
|
|
}
|
|
|
|
epd_update();
|
|
}
|
|
|
|
void epd_displayRED_invert(uint8_t *Image)
|
|
{
|
|
uint32_t Width, Height;
|
|
|
|
Width = EPD_H;
|
|
Height = EPD_W_BUFF_SIZE;
|
|
|
|
epd_setpos(0, 0);
|
|
|
|
epd_write_reg(0x26);
|
|
epd_write_imagedata_invert(Image, Width * Height);
|
|
|
|
if (epd_type == EPD420)
|
|
{
|
|
epd_write_reg(0x21); // Display Update Controll
|
|
epd_write_data(0x00); // RED normal
|
|
epd_write_data(0x00); // single chip application
|
|
}
|
|
|
|
epd_update();
|
|
}
|
|
|
|
void epd_paint_newimage(uint8_t *image, uint16_t Width, uint16_t Height, uint16_t Rotate, uint16_t Color)
|
|
{
|
|
EPD_Paint.Image = 0x00;
|
|
EPD_Paint.Image = image;
|
|
|
|
EPD_Paint.WidthMemory = Width;
|
|
EPD_Paint.HeightMemory = Height;
|
|
EPD_Paint.Color = Color;
|
|
EPD_Paint.WidthByte = (Width % 8 == 0) ? (Width / 8) : (Width / 8 + 1);
|
|
EPD_Paint.HeightByte = Height;
|
|
EPD_Paint.Rotate = Rotate;
|
|
if (Rotate == EPD_ROTATE_0 || Rotate == EPD_ROTATE_180)
|
|
{
|
|
|
|
EPD_Paint.Width = Height;
|
|
EPD_Paint.Height = Width;
|
|
}
|
|
else
|
|
{
|
|
EPD_Paint.Width = Width;
|
|
EPD_Paint.Height = Height;
|
|
}
|
|
}
|
|
|
|
void epd_paint_setpixel(uint16_t Xpoint, uint16_t Ypoint, uint16_t Color)
|
|
{
|
|
uint16_t X, Y;
|
|
uint32_t Addr;
|
|
uint8_t Rdata;
|
|
switch (EPD_Paint.Rotate)
|
|
{
|
|
case 0:
|
|
|
|
X = EPD_Paint.WidthMemory - Ypoint - 1;
|
|
Y = Xpoint;
|
|
break;
|
|
case 90:
|
|
X = EPD_Paint.WidthMemory - Xpoint - 1;
|
|
Y = EPD_Paint.HeightMemory - Ypoint - 1;
|
|
break;
|
|
case 180:
|
|
X = Ypoint;
|
|
Y = EPD_Paint.HeightMemory - Xpoint - 1;
|
|
break;
|
|
case 270:
|
|
X = Xpoint;
|
|
Y = Ypoint;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
Addr = X / 8 + Y * EPD_Paint.WidthByte;
|
|
Rdata = EPD_Paint.Image[Addr];
|
|
if (Color == EPD_COLOR_BLACK)
|
|
{
|
|
EPD_Paint.Image[Addr] = Rdata & ~(0x80 >> (X % 8));
|
|
}
|
|
else
|
|
EPD_Paint.Image[Addr] = Rdata | (0x80 >> (X % 8));
|
|
}
|
|
|
|
void epd_paint_clear(uint16_t color)
|
|
{
|
|
uint16_t X, Y;
|
|
uint32_t Addr;
|
|
|
|
for (Y = 0; Y < EPD_Paint.HeightByte; Y++)
|
|
{
|
|
for (X = 0; X < EPD_Paint.WidthByte; X++)
|
|
{ // 8 pixel = 1 byte
|
|
Addr = X + Y * EPD_Paint.WidthByte;
|
|
EPD_Paint.Image[Addr] = color;
|
|
}
|
|
}
|
|
}
|
|
|
|
void epd_paint_selectimage(uint8_t *image)
|
|
{
|
|
EPD_Paint.Image = image;
|
|
}
|
|
|
|
void epd_paint_drawPoint(uint16_t Xpoint, uint16_t Ypoint, uint16_t Color)
|
|
{
|
|
epd_paint_setpixel(Xpoint - 1, Ypoint - 1, Color);
|
|
}
|
|
|
|
void epd_paint_drawLine(uint16_t Xstart, uint16_t Ystart, uint16_t Xend, uint16_t Yend, uint16_t Color)
|
|
{
|
|
uint16_t Xpoint, Ypoint;
|
|
int32_t dx, dy;
|
|
int32_t XAddway, YAddway;
|
|
int32_t Esp;
|
|
char Dotted_Len;
|
|
Xpoint = Xstart;
|
|
Ypoint = Ystart;
|
|
dx = (int)Xend - (int)Xstart >= 0 ? Xend - Xstart : Xstart - Xend;
|
|
dy = (int)Yend - (int)Ystart <= 0 ? Yend - Ystart : Ystart - Yend;
|
|
|
|
XAddway = Xstart < Xend ? 1 : -1;
|
|
YAddway = Ystart < Yend ? 1 : -1;
|
|
|
|
Esp = dx + dy;
|
|
Dotted_Len = 0;
|
|
|
|
for (;;)
|
|
{
|
|
Dotted_Len++;
|
|
epd_paint_drawPoint(Xpoint, Ypoint, Color);
|
|
if (2 * Esp >= dy)
|
|
{
|
|
if (Xpoint == Xend)
|
|
break;
|
|
Esp += dy;
|
|
Xpoint += XAddway;
|
|
}
|
|
if (2 * Esp <= dx)
|
|
{
|
|
if (Ypoint == Yend)
|
|
break;
|
|
Esp += dx;
|
|
Ypoint += YAddway;
|
|
}
|
|
}
|
|
}
|
|
|
|
void epd_paint_drawRectangle(uint16_t Xstart, uint16_t Ystart, uint16_t Xend, uint16_t Yend, uint16_t Color, uint8_t mode)
|
|
{
|
|
uint16_t i;
|
|
if (mode)
|
|
{
|
|
for (i = Ystart; i < Yend; i++)
|
|
{
|
|
epd_paint_drawLine(Xstart, i, Xend, i, Color);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
epd_paint_drawLine(Xstart, Ystart, Xend, Ystart, Color);
|
|
epd_paint_drawLine(Xstart, Ystart, Xstart, Yend, Color);
|
|
epd_paint_drawLine(Xend, Yend, Xend, Ystart, Color);
|
|
epd_paint_drawLine(Xend, Yend, Xstart, Yend, Color);
|
|
}
|
|
}
|
|
|
|
void epd_paint_drawCircle(uint16_t X_Center, uint16_t Y_Center, uint16_t Radius, uint16_t Color, uint8_t mode)
|
|
{
|
|
int16_t f = 1 - Radius;
|
|
int16_t ddF_x = 1;
|
|
int16_t ddF_y = -2 * Radius;
|
|
int16_t x = 0;
|
|
int16_t y = Radius;
|
|
|
|
if (mode)
|
|
{
|
|
// 实心圆 - 绘制填充线
|
|
epd_paint_drawLine(X_Center - Radius, Y_Center, X_Center + Radius, Y_Center, Color);
|
|
}
|
|
else
|
|
{
|
|
// 空心圆 - 绘制8个对称点
|
|
epd_paint_drawPoint(X_Center, Y_Center + Radius, Color);
|
|
epd_paint_drawPoint(X_Center, Y_Center - Radius, Color);
|
|
epd_paint_drawPoint(X_Center + Radius, Y_Center, Color);
|
|
epd_paint_drawPoint(X_Center - Radius, Y_Center, Color);
|
|
}
|
|
|
|
while (x < y)
|
|
{
|
|
if (f >= 0)
|
|
{
|
|
y--;
|
|
ddF_y += 2;
|
|
f += ddF_y;
|
|
}
|
|
x++;
|
|
ddF_x += 2;
|
|
f += ddF_x;
|
|
|
|
if (mode)
|
|
{
|
|
// 实心圆 - 绘制填充线
|
|
epd_paint_drawLine(X_Center - x, Y_Center + y, X_Center + x, Y_Center + y, Color);
|
|
epd_paint_drawLine(X_Center - x, Y_Center - y, X_Center + x, Y_Center - y, Color);
|
|
epd_paint_drawLine(X_Center - y, Y_Center + x, X_Center + y, Y_Center + x, Color);
|
|
epd_paint_drawLine(X_Center - y, Y_Center - x, X_Center + y, Y_Center - x, Color);
|
|
}
|
|
else
|
|
{
|
|
// 空心圆 - 绘制8个对称点
|
|
epd_paint_drawPoint(X_Center + x, Y_Center + y, Color);
|
|
epd_paint_drawPoint(X_Center - x, Y_Center + y, Color);
|
|
epd_paint_drawPoint(X_Center + x, Y_Center - y, Color);
|
|
epd_paint_drawPoint(X_Center - x, Y_Center - y, Color);
|
|
epd_paint_drawPoint(X_Center + y, Y_Center + x, Color);
|
|
epd_paint_drawPoint(X_Center - y, Y_Center + x, Color);
|
|
epd_paint_drawPoint(X_Center + y, Y_Center - x, Color);
|
|
epd_paint_drawPoint(X_Center - y, Y_Center - x, Color);
|
|
}
|
|
}
|
|
}
|
|
|
|
void epd_paint_showChar(uint16_t x, uint16_t y, uint16_t chr, uint16_t size1, uint16_t color)
|
|
{
|
|
uint16_t i, m, temp, size2, chr1;
|
|
uint16_t x0, y0;
|
|
x += 1, y += 1, x0 = x, y0 = y;
|
|
|
|
if (x >= EPD_H || y >= EPD_W)
|
|
return;
|
|
if (x + size1 > EPD_H || y + 8 > EPD_W)
|
|
return;
|
|
|
|
if (size1 == 8)
|
|
size2 = 6;
|
|
else
|
|
size2 = (size1 / 8 + ((size1 % 8) ? 1 : 0)) * (size1 / 2);
|
|
|
|
chr1 = chr - ' ';
|
|
for (i = 0; i < size2; i++)
|
|
{
|
|
if (size1 == 8)
|
|
{
|
|
temp = asc2_0806[chr1][i];
|
|
}
|
|
else if (size1 == 12)
|
|
{
|
|
temp = asc2_1206[chr1][i];
|
|
}
|
|
else if (size1 == 16)
|
|
{
|
|
temp = asc2_1608[chr1][i];
|
|
}
|
|
else if (size1 == 24)
|
|
{
|
|
temp = asc2_2412[chr1][i];
|
|
}
|
|
else
|
|
return;
|
|
|
|
for (m = 0; m < 8; m++)
|
|
{
|
|
if (y + m >= EPD_W)
|
|
break;
|
|
if (temp & 0x01)
|
|
epd_paint_drawPoint(x, y + m, color);
|
|
else
|
|
epd_paint_drawPoint(x, y + m, !color);
|
|
temp >>= 1;
|
|
}
|
|
x++;
|
|
if ((size1 != 8) && ((x - x0) == size1 / 2))
|
|
{
|
|
x = x0;
|
|
y0 = y0 + 8;
|
|
}
|
|
y = y0;
|
|
}
|
|
}
|
|
|
|
void epd_paint_showString(uint16_t x, uint16_t y, uint8_t *chr, uint16_t size1, uint16_t color)
|
|
{
|
|
while (*chr != '\0')
|
|
{
|
|
epd_paint_showChar(x, y, *chr, size1, color);
|
|
chr++;
|
|
if (size1 == 8)
|
|
{
|
|
x += 6;
|
|
if (x > EPD_H - 6)
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
x += size1 / 2;
|
|
if (x > EPD_H - size1 / 2)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// m^n
|
|
static uint32_t _Pow(uint16_t m, uint16_t n)
|
|
{
|
|
uint32_t result = 1;
|
|
while (n--)
|
|
{
|
|
result *= m;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void epd_paint_showNum(uint16_t x, uint16_t y, uint32_t num, uint16_t len, uint16_t size1, uint16_t color)
|
|
{
|
|
uint8_t t, temp, m = 0;
|
|
if (size1 == 8)
|
|
m = 2;
|
|
for (t = 0; t < len; t++)
|
|
{
|
|
temp = (num / _Pow(10, len - t - 1)) % 10;
|
|
if (temp == 0)
|
|
{
|
|
epd_paint_showChar(x + (size1 / 2 + m) * t, y, '0', size1, color);
|
|
}
|
|
else
|
|
{
|
|
epd_paint_showChar(x + (size1 / 2 + m) * t, y, temp + '0', size1, color);
|
|
}
|
|
}
|
|
}
|
|
|
|
void epd_paint_showChinese(uint16_t x, uint16_t y, uint16_t num, uint16_t size1, uint16_t color)
|
|
{
|
|
uint16_t m, temp;
|
|
uint16_t x0, y0;
|
|
uint16_t i, size3 = (size1 / 8 + ((size1 % 8) ? 1 : 0)) * size1;
|
|
x += 1, y += 1, x0 = x, y0 = y;
|
|
for (i = 0; i < size3; i++)
|
|
{
|
|
if (size1 == 16)
|
|
{
|
|
temp = Hzk1[num][i];
|
|
} // 16*16
|
|
else if (size1 == 24)
|
|
{
|
|
temp = Hzk2[num][i];
|
|
} // 24*24
|
|
else if (size1 == 32)
|
|
{
|
|
temp = Hzk3[num][i];
|
|
} // 32*32
|
|
else if (size1 == 64)
|
|
{
|
|
temp = Hzk4[num][i];
|
|
} // 64*64
|
|
else
|
|
return;
|
|
for (m = 0; m < 8; m++)
|
|
{
|
|
if (temp & 0x01)
|
|
epd_paint_drawPoint(x, y, color);
|
|
else
|
|
epd_paint_drawPoint(x, y, !color);
|
|
temp >>= 1;
|
|
y++;
|
|
}
|
|
x++;
|
|
if ((x - x0) == size1)
|
|
{
|
|
x = x0;
|
|
y0 = y0 + 8;
|
|
}
|
|
y = y0;
|
|
}
|
|
}
|
|
|
|
void epd_paint_showPicture(uint16_t x, uint16_t y, uint16_t sizex, uint16_t sizey, const uint8_t BMP[], uint16_t Color)
|
|
{
|
|
uint16_t j = 0;
|
|
uint16_t i, n = 0, temp = 0, m = 0;
|
|
uint16_t x0 = 0, y0 = 0;
|
|
x += 1, y += 1, x0 = x, y0 = y;
|
|
sizey = sizey / 8 + ((sizey % 8) ? 1 : 0);
|
|
for (n = 0; n < sizey; n++)
|
|
{
|
|
for (i = 0; i < sizex; i++)
|
|
{
|
|
temp = BMP[j];
|
|
j++;
|
|
for (m = 0; m < 8; m++)
|
|
{
|
|
if (temp & 0x01)
|
|
epd_paint_drawPoint(x, y, !Color);
|
|
else
|
|
epd_paint_drawPoint(x, y, Color);
|
|
temp >>= 1;
|
|
y++;
|
|
}
|
|
x++;
|
|
if ((x - x0) == sizex)
|
|
{
|
|
x = x0;
|
|
y0 = y0 + 8;
|
|
}
|
|
y = y0;
|
|
}
|
|
}
|
|
}
|