adafruit / Adafruit_LvGL_Glue

“Glue” library between LittlevGL and Adafruit GFX (SPITFT)
Other
35 stars 14 forks source link

Support for reading images from SD card #12

Closed photomoose closed 3 years ago

photomoose commented 3 years ago

This PR extends Glue by implementing the LVGL file system abstraction so that images can be read directly from an SD card.

A pre-initialized instance of SdFat is required and is supplied as an additional argument to the existing begin() functions.

SdFat Dependency

The Adafruit GFX documentation describing why the Adafruit ImageReader library exists as a separate library (due to the size of the SD dependencies) made me consider how I could make the SD dependency optional in Glue. Conditional compilation via preprocessor directives is not really an option in the Arduino IDE - as a result, I opted to subclass the existing Adafruit_LvGL_Glue class to create a new Adafruit_LvGL_Glue_SD class - applications that wish to read images from the SD card should should this new subclass. Referencing the header file Adafruit_LvGL_Glue_SD.h will bring in the SdFat dependency. Applications that do not require use of the SD card can continue using the existing class (Adafruit_LvGL_Glue).

Example

An example sketch has been included - it will require the cloudy.bin image to be placed at the root of the SD card.

Basic usage

  // Use Adafruit_LvGL_Glue_SD instead of Adafruit_LvGL_Glue
  Adafruit_LvGL_Glue_SD glue;
  SdFat sd;

  // SD controller needs to be initialized before starting Glue
  if (!sd.begin(SD_CS, SD_SCK_MHZ(25))) { // ESP32 requires 25 MHz limit
    Serial.println("Couldn't start SD card controller");
    for(;;);
  }

  // Initialize glue, passing in address of display, touchscreen & SD controller
  LvGLStatus status = glue.begin(&tft, &ts, &sd);

 ...

  // Create and load image from SD
  // Glue maps SD to drive letter S
  lv_obj_t *img = lv_img_create(lv_scr_act(), NULL);
  lv_img_set_src(img, "S:cloudy.bin");

Testing

Tested on an Adafruit HUZZAH ESP32 Feather paired with a 3.5" TFT Featherwing, using both CLion/Platformio and Arduino IDEs. I do not have access to other boards/TFTs.

photomoose commented 3 years ago

@PaintYourDragon following on from our discussion in #11, I've moved the dmaWait() and endWrite() calls into the SD file system callbacks. This works on an ESP32 Feather, however doesn't appear to work on my Feather M0 - I will take a look later and post back my results.

I haven't [yet] put any boolean switch around the calls to dmaWait()/endWrite() as I am assuming they are no-ops if SPI transactions are not enabled/supported - I could be wrong though.

photomoose commented 3 years ago

OK, I've looked into why this doesn't work on my Feather M0 - and that's because there simply isn't enough memory to run LVGL with images (which was the reason I moved to an ESP32 in the first place). The LVGL logs prove this:

/Users/tom.davis/Documents/Arduino/libraries/lvgl/src/lv_core/lv_obj.c@273->Screen create started
/Users/tom.davis/Documents/Arduino/libraries/lvgl/src/lv_core/lv_obj.c@461->Object create ready
/Users/tom.davis/Documents/Arduino/libraries/lvgl/src/lv_core/lv_obj.c@273->Screen create started
/Users/tom.davis/Documents/Arduino/libraries/lvgl/src/lv_core/lv_obj.c@461->Object create ready
/Users/tom.davis/Documents/Arduino/libraries/lvgl/src/lv_core/lv_obj.c@273->Screen create started
/Users/tom.davis/Documents/Arduino/libraries/lvgl/src/lv_core/lv_obj.c@461->Object create ready
Glue started
Creating image
/Users/tom.davis/Documents/Arduino/libraries/lvgl/src/lv_widgets/lv_img.c@62->image create started
/Users/tom.davis/Documents/Arduino/libraries/lvgl/src/lv_core/lv_obj.c@305->Object create started
/Users/tom.davis/Documents/Arduino/libraries/lvgl/src/lv_core/lv_obj.c@461->Object create ready
/Users/tom.davis/Documents/Arduino/libraries/lvgl/src/lv_widgets/lv_img.c@127->image created
Loading image
/Users/tom.davis/Documents/Arduino/libraries/lvgl/src/lv_widgets/lv_label.c@78->label create started
/Users/tom.davis/Documents/Arduino/libraries/lvgl/src/lv_core/lv_obj.c@305->Object create started
/Users/tom.davis/Documents/Arduino/libraries/lvgl/src/lv_core/lv_obj.c@461->Object create ready
/Users/tom.davis/Documents/Arduino/libraries/lvgl/src/lv_widgets/lv_label.c@165->label created
/Users/tom.davis/Documents/Arduino/libraries/lvgl/src/lv_misc/lv_task.c@67->lv_task_handler started
/Users/tom.davis/Documents/Arduino/libraries/lvgl/src/lv_core/lv_refr.c@177->lv_refr_task: started
/Users/tom.davis/Documents/Arduino/libraries/lvgl/src/lv_widgets/lv_img.c@663->lv_img_design: start to draw image
/Users/tom.davis/Documents/Arduino/libraries/lvgl/src/lv_draw/lv_img_cache.c@119->image draw: cache miss, cached to an empty entry
/Users/tom.davis/Documents/Arduino/libraries/lvgl/src/lv_misc/lv_mem.c@199->Couldn't allocate memory
/Users/tom.davis/Documents/Arduino/libraries/lvgl/src/lv_misc/lv_mem.c@306->Couldn't allocate memory
/Users/tom.davis/Documents/Arduino/libraries/lvgl/src/lv_misc/lv_mem.c@511->_lv_mem_buf_get
/Users/tom.davis/Documents/Arduino/libraries/lvgl/src/lv_misc/lv_debug.c@127->Out of memory, can't allocate a new buffer (increase your LV_MEM_SIZE/heap size) (0x00000000)

However, the library works fine with an M0 if you don't do memory intensive graphics.

So, this PR is ready as far as I can tell, awaiting your review.

photomoose commented 3 years ago

@ladyada @PaintYourDragon Did anyone get round to looking at this PR? :-)