Merge pull request #11796 from gemu2015/udisp

add e-paper 4.2 support
This commit is contained in:
Theo Arends 2021-04-19 17:58:06 +02:00 committed by GitHub
commit 08343f5d35
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 282 additions and 36 deletions

View File

@ -52,6 +52,11 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) {
startline = 0xA1;
uint8_t section = 0;
dsp_ncmds = 0;
lut_num = 0;
for (uint32_t cnt = 0; cnt < 5; cnt++) {
lut_cnt[cnt] = 0;
lut_cmd[cnt] = 0xff;
}
char linebuff[128];
while (*lp) {
@ -76,6 +81,12 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) {
allcmd_mode = 1;
lp1++;
}
} else if (section == 'L') {
if (*lp1 >= '1' && *lp1 <= '5') {
lut_num = (*lp1 & 0x07);
lp1+=2;
lut_cmd[lut_num - 1] = next_hex(&lp1);
}
}
if (*lp1 == ',') lp1++;
}
@ -213,13 +224,25 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) {
dim_op = next_hex(&lp1);
break;
case 'L':
while (1) {
if (!str2c(&lp1, ibuff, sizeof(ibuff))) {
lut_full[lutfsize++] = strtol(ibuff, 0, 16);
} else {
break;
if (!lut_num) {
while (1) {
if (!str2c(&lp1, ibuff, sizeof(ibuff))) {
lut_full[lutfsize++] = strtol(ibuff, 0, 16);
} else {
break;
}
if (lutfsize >= LUTMAXSIZE) break;
}
} else {
uint8_t index = lut_num - 1;
while (1) {
if (!str2c(&lp1, ibuff, sizeof(ibuff))) {
lut_array[lut_cnt[index]++][index] = strtol(ibuff, 0, 16);
} else {
break;
}
if (lut_cnt[index] >= LUTMAXSIZE) break;
}
if (lutfsize >= sizeof(lut_full)) break;
}
break;
case 'l':
@ -229,7 +252,7 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) {
} else {
break;
}
if (lutpsize >= sizeof(lut_partial)) break;
if (lutpsize >= LUTMAXSIZE) break;
}
break;
case 'T':
@ -250,9 +273,15 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) {
}
if (lutfsize && lutpsize) {
// 2 table mode
ep_mode = 1;
}
if (lut_cnt[0]>0 && lut_cnt[1]==lut_cnt[2] && lut_cnt[1]==lut_cnt[3] && lut_cnt[1]==lut_cnt[4]) {
// 5 table mode
ep_mode = 2;
}
#ifdef UDSP_DEBUG
Serial.printf("xs : %d\n", gxs);
@ -278,10 +307,18 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) {
Serial.printf("Rot 0: %x,%x - %d - %d\n", madctrl, rot[0], x_addr_offs[0], y_addr_offs[0]);
if (ep_mode) {
if (ep_mode == 1) {
Serial.printf("LUT_Partial : %d\n", lutpsize);
Serial.printf("LUT_Full : %d\n", lutfsize);
}
if (ep_mode == 2) {
Serial.printf("LUT_SIZE 1: %d\n", lut_cnt[0]);
Serial.printf("LUT_SIZE 2: %d\n", lut_cnt[1]);
Serial.printf("LUT_SIZE 3: %d\n", lut_cnt[2]);
Serial.printf("LUT_SIZE 4: %d\n", lut_cnt[3]);
Serial.printf("LUT_SIZE 5: %d\n", lut_cnt[4]);
Serial.printf("LUT_CMDS %02x-%02x-%02x-%02x-%02x\n", lut_cmd[0], lut_cmd[1], lut_cmd[2], lut_cmd[3], lut_cmd[4]);
}
}
if (interface == _UDSP_I2C) {
Serial.printf("Addr : %02x\n", i2caddr);
@ -443,7 +480,7 @@ Renderer *uDisplay::Init(void) {
// must init luts on epaper
if (ep_mode) {
Init_EPD(DISPLAY_INIT_FULL);
Init_EPD(DISPLAY_INIT_PARTIAL);
if (ep_mode == 1) Init_EPD(DISPLAY_INIT_PARTIAL);
}
return this;
@ -451,7 +488,7 @@ Renderer *uDisplay::Init(void) {
void uDisplay::DisplayInit(int8_t p, int8_t size, int8_t rot, int8_t font) {
if (p !=DISPLAY_INIT_MODE && ep_mode) {
if (p != DISPLAY_INIT_MODE && ep_mode) {
if (p == DISPLAY_INIT_PARTIAL) {
if (lutpsize) {
SetLut(lut_partial);
@ -463,8 +500,12 @@ void uDisplay::DisplayInit(int8_t p, int8_t size, int8_t rot, int8_t font) {
if (lutfsize) {
SetLut(lut_full);
Updateframe_EPD();
delay(lutftime * 10);
}
if (ep_mode == 2) {
ClearFrame_42();
DisplayFrame_42();
}
delay(lutftime * 10);
return;
}
} else {
@ -489,14 +530,22 @@ void uDisplay::spi_command(uint8_t val) {
if (spi_dc < 0) {
if (spi_nr > 2) {
write9(val, 0);
if (spi_nr == 3) {
write9(val, 0);
} else {
write9_slow(val, 0);
}
} else {
hw_write9(val, 0);
}
} else {
SPI_DC_LOW
if (spi_nr > 2) {
write8(val);
if (spi_nr == 3) {
write8(val);
} else {
write8_slow(val);
}
} else {
uspi->write(val);
}
@ -507,13 +556,21 @@ void uDisplay::spi_command(uint8_t val) {
void uDisplay::spi_data8(uint8_t val) {
if (spi_dc < 0) {
if (spi_nr > 2) {
write9(val, 1);
if (spi_nr == 3) {
write9(val, 1);
} else {
write9_slow(val, 1);
}
} else {
hw_write9(val, 1);
}
} else {
if (spi_nr > 2) {
write8(val);
if (spi_nr == 3) {
write8(val);
} else {
write8_slow(val);
}
} else {
uspi->write(val);
}
@ -827,6 +884,7 @@ for(y=h; y>0; y--) {
void uDisplay::Splash(void) {
if (ep_mode) {
Updateframe();
delay(lut3time * 10);
}
setTextFont(splash_font);
@ -1230,6 +1288,7 @@ void uDisplay::hw_write9(uint8_t val, uint8_t dc) {
#define USECACHE ICACHE_RAM_ATTR
// slow software spi needed for displays with max 10 Mhz clck
void USECACHE uDisplay::write8(uint8_t val) {
for (uint8_t bit = 0x80; bit; bit >>= 1) {
@ -1240,6 +1299,15 @@ void USECACHE uDisplay::write8(uint8_t val) {
}
}
void uDisplay::write8_slow(uint8_t val) {
for (uint8_t bit = 0x80; bit; bit >>= 1) {
GPIO_CLR_SLOW(spi_clk);
if (val & bit) GPIO_SET_SLOW(spi_mosi);
else GPIO_CLR_SLOW(spi_mosi);
GPIO_SET_SLOW(spi_clk);
}
}
void USECACHE uDisplay::write9(uint8_t val, uint8_t dc) {
GPIO_CLR(spi_clk);
@ -1255,6 +1323,21 @@ void USECACHE uDisplay::write9(uint8_t val, uint8_t dc) {
}
}
void uDisplay::write9_slow(uint8_t val, uint8_t dc) {
GPIO_CLR_SLOW(spi_clk);
if (dc) GPIO_SET_SLOW(spi_mosi);
else GPIO_CLR_SLOW(spi_mosi);
GPIO_SET_SLOW(spi_clk);
for (uint8_t bit = 0x80; bit; bit >>= 1) {
GPIO_CLR_SLOW(spi_clk);
if (val & bit) GPIO_SET_SLOW(spi_mosi);
else GPIO_CLR_SLOW(spi_mosi);
GPIO_SET_SLOW(spi_clk);
}
}
void USECACHE uDisplay::write16(uint16_t val) {
for (uint16_t bit = 0x8000; bit; bit >>= 1) {
GPIO_CLR(spi_clk);
@ -1318,12 +1401,23 @@ void uDisplay::spi_command_EPD(uint8_t val) {
void uDisplay::Init_EPD(int8_t p) {
if (p == DISPLAY_INIT_PARTIAL) {
SetLut(lut_partial);
if (lutpsize) {
SetLut(lut_partial);
}
} else {
SetLut(lut_full);
if (lutfsize) {
SetLut(lut_full);
}
if (lut_cnt[0]) {
SetLuts();
}
}
if (ep_mode == 1) {
ClearFrameMemory(0xFF);
Updateframe_EPD();
} else {
ClearFrame_42();
}
ClearFrameMemory(0xFF);
Updateframe_EPD();
if (p == DISPLAY_INIT_PARTIAL) {
delay(lutptime * 10);
} else {
@ -1341,6 +1435,58 @@ void uDisplay::ClearFrameMemory(unsigned char color) {
}
}
void uDisplay::SetLuts(void) {
uint8_t index, count;
for (index = 0; index < 5; index++) {
spi_command_EPD(lut_cmd[index]); //vcom
for (count = 0; count < lut_cnt[index]; count++) {
spi_data8_EPD(lut_array[count][index]);
}
}
}
void uDisplay::DisplayFrame_42(void) {
uint16_t Width, Height;
Width = (gxs % 8 == 0) ? (gxs / 8 ): (gxs / 8 + 1);
Height = gys;
spi_command_EPD(saw_2);
for (uint16_t j = 0; j < Height; j++) {
for (uint16_t i = 0; i < Width; i++) {
spi_data8_EPD(buffer[i + j * Width] ^ 0xff);
}
}
spi_command_EPD(saw_3);
delay(100);
//Serial.printf("EPD Diplayframe\n");
}
void uDisplay::ClearFrame_42(void) {
uint16_t Width, Height;
Width = (gxs % 8 == 0)? (gxs / 8 ): (gxs / 8 + 1);
Height = gys;
spi_command_EPD(saw_1);
for (uint16_t j = 0; j < Height; j++) {
for (uint16_t i = 0; i < Width; i++) {
spi_data8_EPD(0xFF);
}
}
spi_command_EPD(saw_2);
for (uint16_t j = 0; j < Height; j++) {
for (uint16_t i = 0; i < Width; i++) {
spi_data8_EPD(0xFF);
}
}
spi_command_EPD(saw_3);
delay(100);
//Serial.printf("EPD Clearframe\n");
}
void uDisplay::SetLut(const unsigned char* lut) {
spi_command_EPD(WRITE_LUT_REGISTER);
/* the length of look-up table is 30 bytes */
@ -1350,11 +1496,15 @@ void uDisplay::SetLut(const unsigned char* lut) {
}
void uDisplay::Updateframe_EPD(void) {
SetFrameMemory(buffer, 0, 0, gxs, gys);
DisplayFrame();
if (ep_mode == 1) {
SetFrameMemory(buffer, 0, 0, gxs, gys);
DisplayFrame_29();
} else {
DisplayFrame_42();
}
}
void uDisplay::DisplayFrame(void) {
void uDisplay::DisplayFrame_29(void) {
spi_command_EPD(DISPLAY_UPDATE_CONTROL_2);
spi_data8_EPD(0xC4);
spi_command_EPD(MASTER_ACTIVATION);

View File

@ -44,11 +44,18 @@ enum uColorType { uCOLOR_BW, uCOLOR_COLOR };
#define PIN_OUT_CLEAR 0x60000308
#define GPIO_SET(A) WRITE_PERI_REG( PIN_OUT_SET, 1 << A)
#define GPIO_CLR(A) WRITE_PERI_REG( PIN_OUT_CLEAR, 1 << A)
#define GPIO_CLR_SLOW(A) digitalWrite(A, LOW)
#define GPIO_SET_SLOW(A) digitalWrite(A, HIGH)
#else
#undef GPIO_SET
#define GPIO_SET(A) GPIO.out_w1ts = (1 << A)
#undef GPIO_CLR
#undef GPIO_SET_SLOW
#undef GPIO_CLR_SLOW
#define GPIO_CLR(A) GPIO.out_w1tc = (1 << A)
#define GPIO_SET(A) GPIO.out_w1ts = (1 << A)
#define GPIO_CLR_SLOW(A) digitalWrite(A, LOW)
#define GPIO_SET_SLOW(A) digitalWrite(A, HIGH)
#endif
#define SPI_BEGIN_TRANSACTION if (spi_nr <= 2) uspi->beginTransaction(spiSettings);
@ -60,6 +67,8 @@ enum uColorType { uCOLOR_BW, uCOLOR_COLOR };
#define ESP32_PWM_CHANNEL 1
#define LUTMAXSIZE 64
class uDisplay : public Renderer {
public:
uDisplay(char *);
@ -87,21 +96,25 @@ class uDisplay : public Renderer {
void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
uint32_t str2c(char **sp, char *vp, uint32_t len);
void i2c_command(uint8_t val);
void spi_command(uint8_t val);
void spi_command_one(uint8_t val);
void spi_command(uint8_t val);
void spi_data8(uint8_t val);
void spi_data16(uint16_t val);
void spi_data32(uint32_t val);
void write8(uint8_t val);
void write8_slow(uint8_t val);
void write9(uint8_t val, uint8_t dc);
void write9_slow(uint8_t val, uint8_t dc);
void hw_write9(uint8_t val, uint8_t dc);
void write16(uint16_t val);
void write32(uint32_t val);
void spi_data9(uint8_t d, uint8_t dc);
void WriteColor(uint16_t color);
void SetLut(const unsigned char* lut);
void DisplayFrame(void);
void SetLuts(void);
void DisplayFrame_29(void);
void Updateframe_EPD();
//void DisplayFrame_42(const unsigned char* frame_buffer);
void SetFrameMemory(const unsigned char* image_buffer);
void SetFrameMemory(const unsigned char* image_buffer, uint16_t x, uint16_t y, uint16_t image_width, uint16_t image_height);
void SetMemoryArea(int x_start, int y_start, int x_end, int y_end);
@ -114,7 +127,10 @@ class uDisplay : public Renderer {
void Init_EPD(int8_t p);
void spi_command_EPD(uint8_t val);
void spi_data8_EPD(uint8_t val);
//void SetPartialWindow_42(uint8_t* frame_buffer, int16_t x, int16_t y, int16_t w, int16_t l, int16_t dtm);
void ClearFrameMemory(unsigned char color);
void ClearFrame_42(void);
void DisplayFrame_42(void);
uint8_t strlen_ln(char *str);
int32_t next_val(char **sp);
uint32_t next_hex(char **sp);
@ -176,9 +192,13 @@ class uDisplay : public Renderer {
uint16_t lutftime;
uint16_t lutptime;
uint16_t lut3time;
uint16_t lut_num;
uint8_t ep_mode;
uint8_t lut_full[64];
uint8_t lut_partial[64];
uint8_t lut_full[LUTMAXSIZE];
uint8_t lut_partial[LUTMAXSIZE];
uint8_t lut_array[LUTMAXSIZE][5];
uint8_t lut_cnt[5];
uint8_t lut_cmd[5];
};

View File

@ -0,0 +1,54 @@
H,E-PAPER-42,400,300,1,SPI,1,*,*,*,*,*,*,*,10
:S,1,1,1,0,10,10
:I
01,5,03,00,2b,2b,03
06,3,17,17,17
04,80
00,1,3F
30,1,3C
61,4,01,90,01,2C
82,1,28
50,1,97
:A,10,13,12
:T,450,10,450
:L1,20
00,17,00,00,00,02
00,17,17,00,00,02
00,0A,01,00,00,01
00,0E,0E,00,00,02
00,00,00,00,00,00
00,00,00,00,00,00
00,00,00,00,00,00,00,00
:L2,21
40,17,00,00,00,02
90,17,17,00,00,02
40,0A,01,00,00,01
A0,0E,0E,00,00,02
00,00,00,00,00,00
00,00,00,00,00,00
00,00,00,00,00,00
:L3,22
40,17,00,00,00,02
90,17,17,00,00,02
A0,0A,01,00,00,01
00,0E,0E,00,00,02
00,00,00,00,00,00
00,00,00,00,00,00
00,00,00,00,00,00
:L4,23
80,17,00,00,00,02
90,17,17,00,00,02
80,0A,01,00,00,01
50,0E,0E,00,00,02
00,00,00,00,00,00
00,00,00,00,00,00
00,00,00,00,00,00
:L5,24
80,17,00,00,00,02
90,17,17,00,00,02
80,0A,01,00,00,01
50,0E,0E,00,00,02
00,00,00,00,00,00
00,00,00,00,00,00
00,00,00,00,00,00
#

View File

@ -1,5 +1,5 @@
Display Descriptor files for use with universal display driver.
2 (3) options to select a display driver
4 (3) options to select a display driver
1. file system driven if UFILESYSTEM is in place (preferred option for normal use)
to select a display rename the file to "dispdesc.txt" and put into flash file system.

View File

@ -5199,7 +5199,7 @@ void HandleScriptTextareaConfiguration(void) {
if (Webserver->hasArg("save")) {
ScriptSaveSettings();
HandleConfiguration();
HandleManagement();
return;
}
}

View File

@ -736,19 +736,30 @@ extern FS *ffsp;
{ char *ep = strchr(cp,':');
if (ep) {
static uint8_t *ram_font;
char fname[24];
*ep = 0;
ep++;
if (*cp != '/') {
fname[0] = '/';
fname[1] = 0;
} else {
fname[0] = 0;
}
strlcat(fname, cp, sizeof(fname));
if (!strstr(cp, ".fnt")) {
strlcat(fname, ".fnt", sizeof(fname));
}
if (ffsp) {
File fp;
fp = ffsp->open(cp, "r");
fp = ffsp->open(fname, "r");
if (fp > 0) {
uint32_t size = fp.size();
if (ram_font) free (ram_font);
ram_font = (uint8_t*)special_malloc(size+4);
ram_font = (uint8_t*)special_malloc(size + 4);
fp.read((uint8_t*)ram_font, size);
fp.close();
if (renderer) renderer->SetRamfont(ram_font);
Serial.printf("Font loaded: %s\n",cp );
//Serial.printf("Font loaded: %s\n",fname );
}
}
cp = ep;

View File

@ -182,6 +182,15 @@ char *fbuff;
replacepin(&cp, Pin(GPIO_BACKLIGHT));
replacepin(&cp, Pin(GPIO_OLED_RESET));
replacepin(&cp, Pin(GPIO_SPI_MISO));
} else if (*cp == '2') {
cp+=2;
replacepin(&cp, Pin(GPIO_SPI_CS, 1));
replacepin(&cp, Pin(GPIO_SPI_CLK, 1));
replacepin(&cp, Pin(GPIO_SPI_MOSI, 1));
replacepin(&cp, Pin(GPIO_SPI_DC, 1));
replacepin(&cp, Pin(GPIO_BACKLIGHT, 1));
replacepin(&cp, Pin(GPIO_OLED_RESET, 1));
replacepin(&cp, Pin(GPIO_SPI_MISO, 1));
} else {
// soft spi pins
cp+=2;
@ -211,20 +220,22 @@ char *fbuff;
cp = strstr(ddesc, ":TI");
if (cp) {
uint8_t wire_n = 1;
cp+=3;
cp += 3;
wire_n = (*cp & 3) - 1;
cp+=2;
cp += 2;
uint8_t i2caddr = strtol(cp, &cp, 16);
int8_t scl, sda;
scl = replacepin(&cp, Pin(GPIO_I2C_SCL));
sda = replacepin(&cp, Pin(GPIO_I2C_SDA));
if (wire_n == 0) {
scl = replacepin(&cp, Pin(GPIO_I2C_SCL));
sda = replacepin(&cp, Pin(GPIO_I2C_SDA));
Wire.begin(sda, scl);
}
#ifdef ESP32
if (wire_n == 1) {
scl = replacepin(&cp, Pin(GPIO_I2C_SCL, 1));
sda = replacepin(&cp, Pin(GPIO_I2C_SDA, 1));
Wire1.begin(sda, scl, 400000);
}
#endif