lovyan03 / LovyanGFX

SPI LCD graphics library for ESP32 (ESP-IDF/ArduinoESP32) / ESP8266 (ArduinoESP8266) / SAMD51(Seeed ArduinoSAMD51)
Other
1.03k stars 189 forks source link

Grayscales in epaper with IT8951 Model: ED078kc2 1872*1404 #147

Closed martinberlin closed 1 year ago

martinberlin commented 2 years ago

First I wanted to say that I really like how this component works and it was a pleasure to install, just a git submodule add Repo components/LovyanGFX And after checking the custom settings it was already working.

What I could not understand yet is how the colors are represented for this 16 grayscale epapers. I use another library for parallel that is called EPDiy and there 0 is black and 255 is white. When I try to do 200x200 squares with incrementing colors from 0 to 70 this is what I get: grayscales

This is using epd_fast mode (in epd_quality works bad for me) It looks like after color:30 it starts to get darker again. Can someone please explain or show an example on how to draw the 16 grayscales in one of this epaper?

On another topic: Can be that the VCOM setting, or the Waveform for this model, is different than the one of M5 epaper?

Further info this is the jpeg-render example that I'm trying with my own component: https://github.com/martinberlin/cale-idf/tree/feature/45-it8951/main/www-jpg-render Render of a cat

lovyan03 commented 2 years ago

@martinberlin Thanks for liking LovyanGFX !

LovyanGFX renders E-Paper and monochrome OLEDs by converting RGB colors to grayscale or monochrome tile patterns. If you specify a value in int 0~255, it will be interpreted as a RGB565 value, and thus will not be correctly grayscaled.

Try the following sample code to see if the grayscale can be drawn correctly.

LGFX display;

display.init();

for (int i = 0; i < 256; ++i)
{
  display.fillRect(i*2, 0, 2, 100, display.color888(i, i, i));
}
martinberlin commented 2 years ago

Fantastic. I can't wait to arrive home and try it. Will make also another photo to show how it works. Thanks a lot! In the JPG render example link I'm experimenting to download and render a JPEG using differing techniques (Requires an ESP32 with PSRAM since needs a decompress buffer)

lovyan03 commented 2 years ago

LovyanGFX has a "drawJpg" function. By writing "#include " or "#include " before "#include ", drawJpgFile / drawJpgUrl functions are available. Since it uses a stream, there is no need to store it in PSRAM.

#define LGFX_USE_V1

#include <esp_wifi.h>
#include <HTTPClient.h>
#include <SD.h>

#include <LovyanGFX.hpp>
#include "LGFX_USERSETTING.h"

LGFX display;

void setup(void)
{
  WiFi.begin();

  display.init();
  display.drawJpgFile(SD, "/image_001.jpg", 0, 0);
  display.drawPngFile(SD, "/image_001.png", 0, 0);
  display.drawBmpFile(SD, "/image_001.bmp", 0, 0);

  display.drawJpgUrl("http://examples/dummy.jpg", 0, 0);
  display.drawPngUrl("http://examples/dummy.png", 0, 0);
  display.drawBmpUrl("http://examples/dummy.bmp", 0, 0);
}
martinberlin commented 2 years ago

Thanks it looks great now! D5FC9FD4-EA73-44F6-B47A-F27E9E8FE7BC Your component is awesome!

martinberlin commented 2 years ago

Reopening since sending this large buffer per SPI I'm getting an wdt alert:

0x400d76ac: task_wdt_isr at /home/martin/esp/esp-idf/components/esp_common/src/task_wdt.c:187

0x40084d89: _xt_lowint1 at /home/martin/esp/esp-idf/components/freertos/xtensa/xtensa_vectors.S:1105

0x400dc83d: lgfx::v1::Bus_SPI::writeData(unsigned int, unsigned int) at /home/martin/esp/projects/cale-idf/components/LovyanGFX/src/lgfx/v1/platforms/esp32/Bus_SPI.cpp:196

0x400db87a: lgfx::v1::Panel_IT8951::_write_args(unsigned short, unsigned short*, int) at /home/martin/esp/projects/cale-idf/components/LovyanGFX/src/lgfx/v1/panel/Panel_IT8951.cpp:257

Will try to solve it adding a small VTaskDelay and feeding the watchdog. Not sure if it’s strictly related to your component feel free to close.

lovyan03 commented 2 years ago

@martinberlin I looked at your program. I see that drawing with drawPixel must be slow. This should be all you need to do in the function tjd_output.

  uint32_t w = rect->right - rect->left + 1;
  uint32_t h = rect->bottom - rect->top + 1;
  display.pushImage(rect->left, rect->top, w, h, (lgfx::bgr888_t*)bitmap);

Since the pushImage function correctly handles the case where the image extends beyond the screen, there is no need for clipping in advance.

If you need to do the gamma correction in advance, you can prepare a uint8_t array and cast it to the lgfx::grayscale_t* type for drawing.

  uint32_t w = rect->right - rect->left + 1;
  uint32_t h = rect->bottom - rect->top + 1;
  uint8_t buf[w*h];
  for (uint32_t i = 0; i < w * h; ++i)
  {
    uint8_t r = *(bitmap_ptr++);
    uint8_t g = *(bitmap_ptr++);
    uint8_t b = *(bitmap_ptr++);
    buf[i] = (r*38 + g*75 + b*15)>>7;
  }
  display.pushImage(rect->left, rect->top, w, h, (lgfx::grayscale_t*)buf);
martinberlin commented 2 years ago

Awesome will try it today. It’s possible also to add dithering so the grayscale transitions are not that visible? Anyways looks awesome and works great. So glad to find your component! 93091D89-FC18-4675-BC90-DBF25D5A121F 201D6519-A07D-434C-B15F-59263CC4D6EC Will measure the time it takes now with drawPixel vs pushImage and post here to compare the optimization before closing. Thanks a lot for your help!

UPDATE: I wanted also to mention that if you need WiFi image galleries to test your displays, you can use my free image service cale.es to do so CALE_Integrations It's not very user-friendly, but it let's you connect Screens with content parts, such as Google Calendar or image Galleries (Even HTML parts)

lovyan03 commented 2 years ago

@martinberlin A big thank you for your sponsorship !!

Come to think of it, you first said "This is using epd_fast mode (in epd_quality works bad for me)" The epd_fast and epd_fastest modes allow the EPD to operate in monochrome binary. and, LovyanGFX uses a 4×4 16pixel tile pattern to display a pseudo 17level grayscale.

If the epd_quality mode works, it will make the EPD work with 16 levels of grayscale. and, LovyanGFX can use a 4×4 16pixel tile pattern to display a pseudo 255level grayscale.

IT8951 should be able to use epd_quality mode, but what problems are you experiencing?

martinberlin commented 2 years ago

No problem, a pleasure to support you. Wow! Now I see so that pool picture is rendered using only monochrome tile pattern. Only zooming in I can see it, I would have bet it was using the 16 grayscales :) So I will try today again. At the beginning it was off for me, like if the Waveshare of this big EPD would be different from the M5 epaper. But I had also the wrong grayscale calculation. I will find sometime today to try this again and report back to you. Also with some statistics of using drawPixel vs pushImage.

STATISTICS draw: 32387 ms . image render using drawPixel on every tjd_output MCU call (32 seconds)

draw: 3382 ms . image render with pushImg with gamma corrrection (10x faster)

Without gamma correction is faster and works awesome!

Total time calculation I (33365) JPG: width: 1872 height: 1404

I (33365) decode: 14183 ms . image decompression I (33365) www-dw: 19764 ms - download I (33375) draw: 3285 ms . image render I (33375) total: 37232 ms - total time spent

Gamma correction now fixed. It just takes some milliseconds more. Awesome again! Many thanks

martinberlin commented 2 years ago

Thanks for all your support. Confirmed that your component works without problems in bigger epapers driven by IT8951 fast mode 33601FB0-01B7-48B2-9B84-9E6D5333039B

And also epd_quality mode works great. 46B09A08-2B48-410F-A901-758C08BFBF11

martinberlin commented 2 years ago

Sorry I'm reopening this one, since I tried to update the component Lovyan GFX to the latest stand, and the colors changed dramatically: Lovyan-latest-update

CODE is the same as when I started this ticket where you drive me to the right results: https://github.com/martinberlin/cale-idf/blob/feature/45-it8951/main/www-jpg-render/main/jpg-render-it8951.cpp

Has anything changed regarding the colors in the latest updates that I need to be aware of?

The colors seem inverted. Other than that the SPI communications part works correctly.

martinberlin commented 2 years ago

My bad I was using an image that had the wrong bit-depth :) I will create a new Issue for my tests with ESP32S3 and new Goodisplay adapter

Note: One thing though that comes all the time when working with big displays is the WDT alert in the monitor

0x400e9b3f: task_wdt_isr at /home/martin/esp/esp-idf/components/esp_system/task_wdt.c:183 (discriminator 3)

0x40085479: _xt_lowint1 at /home/martin/esp/esp-idf/components/freertos/port/xtensa/xtensa_vectors.S:1111

0x400ddc38: lgfx::v1::Panel_IT8951::_wait_busy(unsigned int) at /home/martin/esp/projects/cale-idf/components/LovyanGFX/src/lgfx/v1/panel/../platforms/esp32/common.hpp:44
 (inlined by) lgfx::v1::Panel_IT8951::_wait_busy(unsigned int) at /home/martin/esp/projects/cale-idf/components/LovyanGFX/src/lgfx/v1/panel/Panel_IT8951.cpp:184

0x400de6df: lgfx::v1::Panel_IT8951::writeImage(unsigned int, unsigned int, unsigned int, unsigned int, lgfx::v1::pixelcopy_t*, bool) at /home/martin/esp/projects/cale-idf/components/LovyanGFX/src/lgfx/v1/panel/Panel_IT8951.cpp:569

0x4016b193: lgfx::v1::LGFXBase::pushImage(int, int, int, int, lgfx::v1::pixelcopy_t*, bool) at /home/martin/esp/projects/cale-idf/components/LovyanGFX/src/lgfx/v1/LGFXBase.cpp:1122

0x400db06f: void lgfx::v1::LGFXBase::pushImage<lgfx::v1::bgr888_t>(int, int, int, int, lgfx::v1::bgr888_t const*) at /home/martin/esp/projects/cale-idf/components/LovyanGFX/src/lgfx/v1/LGFXBase.hpp:258
 (inlined by) tjd_output at /home/martin/esp/projects/cale-idf/main/www-jpg-render/build/../main/jpg-render-it8951.cpp:289

0x400db60e: drawBufJpeg(unsigned char*, int, int) at /home/martin/esp/projects/cale-idf/main/www-jpg-render/build/../main/jpg-render-it8951.cpp:311

0x400db814: _http_event_handler(esp_http_client_event*) at /home/martin/esp/projects/cale-idf/main/www-jpg-render/build/../main/jpg-render-it8951.cpp:371

0x4016c976: http_dispatch_event at /home/martin/esp/esp-idf/components/esp_http_client/esp_http_client.c:179

0x40107e1e: esp_http_client_perform at /home/martin/esp/esp-idf/components/esp_http_client/esp_http_client.c:1171

0x400db539: http_post() at /home/martin/esp/projects/cale-idf/main/www-jpg-render/build/../main/jpg-render-it8951.cpp:418

0x400dbc96: app_main at /home/martin/esp/projects/cale-idf/main/www-jpg-render/build/../main/jpg-render-it8951.cpp:580

0x40170673: main_task at /home/martin/esp/esp-idf/components/freertos/port/port_common.c:129 (discriminator 2)

0x40090e75: vPortTaskWrapper at /home/martin/esp/esp-idf/components/freertos/port/xtensa/port.c:131

This alerts make the Firmware work really slow, would it be possible to reduce them somehow?

martinberlin commented 2 years ago

After fighting with this quite long, I realize that is not Lovyan update that is making the picture to render strange, but rather that I'm testing now with a more modern IDF: ESP-IDF v4.4

All the images look exactly like shown here. Sorry to bother you @lovyan03 but can you give me some advice?

I'm also designing a new PCB for Goodisplay ITE 9.7 (1800*825) IT8951 controller and I would really like to use your component to build my Firmware examples. This is based on ESP32S3 and I'm still testing it since it seems a bit different than the Waveshare model.

martinberlin commented 2 years ago

Interesting note: Switching to ESP-IDF version <= 4.3 then grayscales work as before. But only renders half of the image (I mean exactly half) I'm quite sure there is some issue with IDF versions, since when I last tested this with v4.2 I could get the full image rendered correctly. So I'm sure that Lovyan component, is suffering from certain updates in the IDF frameworks, just like many other libraries (including mines) Happy to help in anything I can.

UPDATE: Disconnecting it from USB and leaving it to work from the battery it renders the full image. So this effect is not associated with Lovyan at all. The only remaining point is to discover why upgrading the IDF framework to v4.4 is affecting the colors.

lovyan03 commented 2 years ago

@martinberlin Sorry, the IT8951 I have is only M5Paper made by M5Stack, so I may not be able to reproduce your situation there.

I see you are using tjpgd provided by ESP-IDF instead of drawJpg from LovyanGFX. Maybe something has changed with the upgrade of ESP-IDF. For comparison, try using LovyanGFX's drawJpg and see if the image is displayed correctly.

martinberlin commented 1 year ago

No problem, will try. Closing this since it works just like before, the only problem seems to be the IDF version >4.4