Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can LovyanGFX support the sdmmc ? #513

Open
zhjygit opened this issue Jan 22, 2024 · 21 comments
Open

How can LovyanGFX support the sdmmc ? #513

zhjygit opened this issue Jan 22, 2024 · 21 comments
Labels
pinned exempt from stale bot

Comments

@zhjygit
Copy link

zhjygit commented Jan 22, 2024

Here, i have a esp32s3-groom1-N16R8-lcd4.3,my tf cart is sdmmc type.
If I want to read the png maps from sd card and draw the picture on the tft display via the gps location datas.
Most of the code on github is about the spiSD card, how can LovyanGFX support the sdmmc?
Waiting for you reply.
Here is my project:https://github.com/jgauchia/IceNav-v3, this project uses the LovyanGFX and spiSD card.
Maybe you can solve the problem.

@zhjygit zhjygit added the enhancement New feature or request label Jan 22, 2024
Copy link

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@github-actions github-actions bot added the stale Inactive issues label Feb 21, 2024
@tobozo tobozo removed the enhancement New feature or request label Feb 21, 2024
@tobozo
Copy link
Collaborator

tobozo commented Feb 21, 2024

just include FS.h or SD.h before including LovyanGFX (e.g. insert #include <FS.h> at first line of hardware/tft.h) and it will expose LGFX filesystem related functions.

however it's more practical to just stick with Stream related functions e.g. :

auto jpgFile = SD.open("/path/to/my-image.jpg");
tft.drawJpg( &jpgFile );

@github-actions github-actions bot removed the stale Inactive issues label Feb 21, 2024
@daverathbone
Copy link

daverathbone commented Mar 7, 2024

This works for Arduino ESP32 , have not tried yet with ESP32 IDF >5.00 and written the function changes:-
Also not tested with ESP S3 or ESP C3 yet....

// updated include order as per Tobozo comment below
#define LGFX_USE_V1
#include <FS.h>
#include <SD.h>
#include <SPI.h>
#include <LovyanGFX.hpp>


There is no SDcard SPI CS in LovyanGFX LCD SPI setup
So native file handling has to be set up with includes FS/SD as normal for SD card (See SDTest in exmples for ESP32)
SD card is SPI and if your LCD is an SPI type you will be sharing MISIO,MOSI and CLK so cfg.bus_shared = true; !!!

I used CS as 5 for LCD and CS as 4 for SD card
Here is my SD card pin out (Arduino default VSPI)
3V3 to 3V3 pin
CS 4 (GPIO4) -- NOT Default for Arduino SD card
MOSI 23 (GPIO23) --Default for Arduino SD card
CLK 18 (GPIO18)- -Default for Arduino SD card
MISO 19 (GPIO19)--Default for Arduino SD card
GND to GND pin

***** Place your LGFX setup class next *******
Use Examples Howtouse/usersetting as a guide translate Japanese with google translate

I have ILI9488 (SPI) LCD , with Touch IC FT6336 (I2C) and LED Backlight that can use PWM

// NOT SHOWN IN FULL 
class LGFX : public lgfx::LGFX_Device
{
    lgfx::Panel_ILI9488     _panel_instance;
    lgfx::Bus_SPI           _bus_instance;   // SPI bus instance
    lgfx::Light_PWM         _light_instance;
    lgfx::Touch_FT5x06       _touch_instance; // FT5206, FT5306, FT5406, FT6206, FT6236, FT6336, FT6436
//..................

// Configure bus control settings........... 
    cfg.spi_host = VSPI_HOST; // Select the SPI to use VSPI_HOST 
// ................
    cfg.pin_sclk =  18; // Set SPI SCLK pin number
    cfg.pin_mosi = 23; // Set the SPI MOSI pin number
    cfg.pin_miso = 19; // Set SPI MISO pin number (-1 = disable)
    cfg.pin_dc =     22; // Set SPI D/C pin number (-1 = disable)
//.............
// Set display panel control......................
    cfg.pin_cs = 5; // Pin number to which CS is connected (-1 = disable)
    cfg.pin_rst = 3 ; // Pin number to which RST is connected (-1 = disable)  (I use EN pin)
//.............
// IPS LCD's may need cfg.invert = true;
// remember !! cfg.bus_shared = true;
//.............

// Set backlight control ......................
    cfg.pin_bl = 21;  // Pin number to which the backlight is connected
//Configure touch screen control settings. ...................
//...................
    cfg.pin_int    = 25;  //Pin number to which Touch  INT is connected
// ..................
// For I2C connection
    cfg.i2c_port = 1; // Select I2C to use (0 or 1)
    cfg.i2c_addr = 0x38; // I2C device address number
    cfg.pin_sda = 33; // Pin number to which SDA is connected
    cfg.pin_scl = 32; // Pin number to which SCL is connected
    cfg.freq = 400000; // Set I2C clock
 _touch_instance.config(cfg);
     _panel_instance.setTouch(&_touch_instance);  // タッチスクリーンをパネルにセットします。
   }
    setPanel(&_panel_instance); // Set the panel to use.
  }
};

LGFX lcd;
/*
Example to show how to place a PNG picture on screen at any  X,,Y  or scale etc.
Note this streams the file from the SD card and fixes the SD card CS issues I had.
See call in loop... Note:  'Auto' is C++ in Aurdino main 
Take care if  calling from C  maybe within a ESP IDF C based code source
*/
void drawPng(
 fs::FS &fs,
 const char *filename,
 int32_t x=0,
 int32_t y=0,
 int32_t maxW =-1,
 int32_t maxH = -1,
 int32_t offX =0,
 int32_t offY = 0,
 float scale_x =1.0F ,
 float scale_y =1.0f,
 textdatum_t datum = TL_DATUM
 ){
 auto pngFile = fs.open(filename);
 if(!pngFile){
    Serial.println("Failed to open the image file.");
 } else {
   lcd.drawPng( &pngFile,x,y,maxW,maxH,offX,offY,datum);
   pngFile.close();
 }
}


// Example function to show fies on sdcard to LCD display 
void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
   Serial.printf("Listing directory: %s\n", dirname);

   File root = fs.open(dirname);
   if(!root){
       Serial.println("Failed to open directory");
       return;
   }
   if(!root.isDirectory()){
       Serial.println("Not a directory");
       return;
   }

   File file = root.openNextFile();
   lcd.setCursor(0, 0);
   lcd.setTextColor(TFT_WHITE);	
   lcd.setFont( &fonts::Font0   );
   while(file){
       

       if(file.isDirectory()){
           Serial.print("  DIR : ");
           Serial.println(file.name());
           lcd.print(("  DIR : "));
           lcd.println(file.name());
           if(levels){
               listDir(fs, file.path(), levels -1);
           }
       } else {
           Serial.print("  FILE: ");
           Serial.print(file.name());
           Serial.print("  SIZE: ");
           Serial.println(file.size());

           lcd.print("  FILE: ");
           lcd.print(file.name());
           lcd.print("  SIZE: ");
           lcd.println(file.size());
        
       }
       file = root.openNextFile();
   }
}

//Example Setup for SDcard, LCD and touch
void setup(void)
{
 Serial.begin(115200);
   if(!SD.begin(4)){  // Note call it with 4 if thats your SD card CS
       Serial.println("Card Mount Failed");
       return;
   }
   uint8_t cardType = SD.cardType();

   if(cardType == CARD_NONE){
       Serial.println("No SD card attached");
       return;
   }

   Serial.print("SD Card Type: ");
   if(cardType == CARD_MMC){
       Serial.println("MMC");
   } else if(cardType == CARD_SD){
       Serial.println("SDSC");
   } else if(cardType == CARD_SDHC){
       Serial.println("SDHC");
   } else {
       Serial.println("UNKNOWN");
   }

   uint64_t cardSize = SD.cardSize() / (1024 * 1024);
   Serial.printf("SD Card Size: %lluMB\n", cardSize);
   lcd.init();
   lcd.begin();        
   lcd.setRotation(3);  // My LCD is 420x320 ribbon to the left 
   lcd.setBrightness(255); // Change to lower LED backlight 
   lcd.clear(TFT_BLACK);
   lcd.setCursor(0, 0);
   lcd.setTextColor(TFT_WHITE);
   lcd.setTextSize((std::max(lcd.width(), lcd.height()) + 255) >> 8);

//  Calibrate when touch is available. (Optional)
 if (lcd.touch())
 {
   if (lcd.width() < lcd.height()) lcd.setRotation(lcd.getRotation() ^ 1);

   // Draw the guide text on the screen.
   lcd.setTextDatum(textdatum_t::middle_center);
   lcd.drawString("touch the arrow marker.", lcd.width()>>1, lcd.height() >> 1);
   lcd.setTextDatum(textdatum_t::top_left);

   // Calibrate when using touch. Touch the tips of the arrows displayed at the four corners of the screen in order.
   std::uint16_t fg = TFT_WHITE;
   std::uint16_t bg = TFT_BLACK;
   if (lcd.isEPD()) std::swap(fg, bg);
   lcd.calibrateTouch(nullptr, fg, bg, std::max(lcd.width(), lcd.height()) >> 3);
 }
// After clear screen show some text and enter loop
 lcd.clear(TFT_BLACK);
 lcd.drawString("Demo here", 0, 0);
 lcd.drawString("Draw on screen", (lcd.width()/2)-80, lcd.height()-20);
}
//Main Arduino loop
void loop(void)
{

 //Example touch loop
 int32_t x, y;
 if (lcd.getTouch(&x, &y)) {
   // make top left hand corner a touch zone
     if(x<20 && y<20){
       lcd.fillScreen(TFT_BLACK);
       drawPng(SD,"/logo.png",0,100);  // Note make sure your SDcard as a png image keep small
       listDir(SD, "/", 0);            // Show the dir with files in root (dont have lots about 6 files)
     }
   
   lcd.fillRect(x-2, y-2, 2, 2, TFT_WHITE);    // places dot for each touch position
 }
 delay(1); // Note on Arduino loop is FreeRTOS task loop 
 // with no vTaskDelay(pdMS_TO_TICKS(100)); so can fire watchdog time out
 // if loop run without giving some CPU time for tasks
 // I think Arduino delay is made from vTaskDelay so may fix this issue?
}

@tobozo
Copy link
Collaborator

tobozo commented Mar 7, 2024

ths is wrong:

#define LGFX_USE_V1
#include <LovyanGFX.hpp>
#include "FS.h"
#include "SD.h"
#include "SPI.h

by doing so you just create two different instances of LovyanGFX, one with filesystem support (sketch scope) and one without it (global scope).

This works for Arduino ESP32

and it probably fails with platformio and esp-idf

filesystem related libraries should be included before LovyanGFX to prevent this:

#define LGFX_USE_V1
#include <FS.h>
#include <SD.h>
#include <SPI.h>
#include <LovyanGFX.hpp>

@mhaberler
Copy link

@daverathbone if this works for you, please share a link
I am particularly interested in working examples using SdFat / exFat working with SPI shared between SD and display

thanks!

@daverathbone
Copy link

daverathbone commented Mar 8, 2024

@daverathbone if this works for you, please share a link I am particularly interested in working examples using SdFat / exFat working with SPI shared between SD and display

thanks!

The format for your SDcard is handled external to the display code suggest you get an example running with your SD card format first , e.g. read file, open file etc. then the streaming or file handling should use the standard C/C++ file handling within LovyanGFX calls.

@mhaberler
Copy link

@daverathbone I considered that, but the application requires a 64bit filesystem and DataWrapper is all 32bit

I want to nail down the specific requirements in setup and calling sequence to have both the SD and display on the same bus. Very easy to create to have a display operation kill SD I/O and vice versa.

This repo https://github.com/GOB52/M5Stack_FlipBookSD has a working example of SdFat I/O and M5Unified/M5GFX - I want the same for LovyanGFX.

The whole thing is a bit of black art; for example it took me the above repo to get this to work - it is unclear to me why

        M5.Display.startWrite();
        M5.Display.clear(TFT_RED);
        M5.Display.endWrite();

is ok, but

        display.startWrite();
        display.clear(TFT_RED);
        display.endWrite();

brings down the house.

@tobozo
Copy link
Collaborator

tobozo commented Mar 8, 2024

@mhaberler

M5Unified can manage more than one display, so aliasing display to M5.Display before the init occured may be the reason why you get a crash when using the alias.

M5Unified.hpp

    M5GFX Display;  // setPrimaryされたディスプレイのインスタンス
    M5GFX &Lcd = Display;

Personnally I find the macro to be more reliable than the global declaration:

#define myDisplay M5.Display

@mhaberler
Copy link

mhaberler commented Mar 8, 2024

oh ok, observed behaviour starts making sense now - will adopt your macro practice

how did you find your way to this result ;-?

edit: tried, house still standing ;)

mhaberler pushed a commit to mhaberler/embedded-protomaps that referenced this issue Mar 8, 2024
@tobozo
Copy link
Collaborator

tobozo commented Mar 8, 2024

how did you find your way to this result ;-?

by pulling my hair with M5Stack-SD-Updater context guessing

@mhaberler
Copy link

great, so the M5Unified version works fine with simultaneous display and SD/SdFat use

trying to use non-M5 boards, I massaged that code to use LovyanGFX and I'm back at square 1 - using display disables SD card

is this possible in principle after all, or does the status #491 apply (i.e. unresolved)?

works fine for target coreS3-pmtiles-m5unified, breaks for coreS3-pmtiles-lovyangfx
https://github.com/mhaberler/embedded-protomaps/commits/lovyangfx/

@sukesh-ak
Copy link

sukesh-ak commented Mar 27, 2024

If display and SD card are on the same SPI Bus, then you need to do this

https://github.com/sukesh-ak/ESP32-TUX/blob/47639648a37ffc9ef9c2a748eeb9761894b9238a/main/devices/conf_WT32SCO1.h#L120

cfg.bus_shared = true;    // Set to true when sharing the bus with sd card (bus control is performed with drawJpgFile, etc.)

And then don't initialize the bus again. Both options are demonstrated in my ESP32-TUX project.

@tobozo
Copy link
Collaborator

tobozo commented Mar 28, 2024

found this old gist with a very slow buf safe approach to sharing the bus, not sure if it's still working though

mhaberler pushed a commit to mhaberler/LovyanGFX that referenced this issue Apr 1, 2024
      // lovyan03#513 (comment)
      _cfg.bus_shared = true;    // Set to true when sharing the bus with sd card (bus control is performed with drawJpgFile, etc.)
Copy link

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@github-actions github-actions bot added the stale Inactive issues label Apr 27, 2024
@mhaberler
Copy link

not stale

@github-actions github-actions bot removed the stale Inactive issues label Apr 27, 2024
Copy link

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@github-actions github-actions bot added the stale Inactive issues label May 27, 2024
@tobozo
Copy link
Collaborator

tobozo commented May 27, 2024

bump

@tobozo tobozo removed the stale Inactive issues label May 27, 2024
Copy link

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@github-actions github-actions bot added the stale Inactive issues label Jun 26, 2024
@tobozo tobozo removed the stale Inactive issues label Jun 26, 2024
Copy link

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@github-actions github-actions bot added the stale Inactive issues label Jul 26, 2024
@tobozo tobozo added pinned exempt from stale bot and removed stale Inactive issues labels Jul 26, 2024
@jgauchia
Copy link

jgauchia commented Aug 9, 2024

Here, i have a esp32s3-groom1-N16R8-lcd4.3,my tf cart is sdmmc type. If I want to read the png maps from sd card and draw the picture on the tft display via the gps location datas. Most of the code on github is about the spiSD card, how can LovyanGFX support the sdmmc? Waiting for you reply. Here is my project:https://github.com/jgauchia/IceNav-v3, this project uses the LovyanGFX and spiSD card. Maybe you can solve the problem.

Hi @zhjygit really is your project? ,
You forked it? Please, don't say that project is yours. thank you

@jgauchia
Copy link

jgauchia commented Aug 9, 2024

@daverathbone if this works for you, please share a link I am particularly interested in working examples using SdFat / exFat working with SPI shared between SD and display

thanks!

Hi @mhaberler I'm working now with SD and TFT shared SPI without goods results, With separated SPI buses I don't have any problem.

Solved with #513 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pinned exempt from stale bot
Projects
None yet
Development

No branches or pull requests

6 participants