Xiao ESP32S3 Sense read MicroSD

Exercise run on Xiao ESP32S3 Sense in Arduino framework, read SD Card. Base on the exercise "240x240 ST7789V2 SPI IPS with FT6236 cap touch on XIAO ESP32S3 using GFX Library for Arduino", display ST7789 LCD.



XiaoS3_ST7789_SD.ino, read and display SD info and hello.txt content.
/*******************************************************************************
Xiao ESP32S3 Sense exercise
 ******************************************************************************/

/*******************************************************************************
 * Start of Arduino_GFX setting
 ******************************************************************************/
 #include <Arduino_GFX_Library.h>
//=== Custom to match my connection ===========================================

#define PIN_BLK 4
#define PIN_CS  3
#define PIN_DC  2
#define PIN_RES 1
#define PIN_SDA 9
#define PIN_SCL 7

#define GFX_BL PIN_BLK

#define CTP_INT 43
#define CTP_RST 44

#define FT6236_ADDR 0x38

#define DISP_WIDTH 240
#define DISP_HEIGHT 240

Arduino_DataBus *bus = new Arduino_HWSPI(PIN_DC, PIN_CS);
Arduino_GFX *gfx = new Arduino_ST7789(bus, PIN_RES, 0 /* rotation */, true /* IPS */, DISP_WIDTH, DISP_HEIGHT);
/*******************************************************************************
 * End of Arduino_GFX setting
 ******************************************************************************/

// SD
#include <SD.h>
#define SD_CS         21

void readFile(fs::FS &fs, const char *path) {
  Serial.printf("Reading file: %s\n", path);
  gfx->printf("Reading file: %s\n", path);

  File file = fs.open(path);
  if (!file) {
    Serial.println("Failed to open file for reading");
    gfx->println("Failed to open file for reading");
    return;
  }

  Serial.print("Read from file: ");
  while (file.available()) {
    char c = file.read();
    Serial.write(c);
    gfx->write(c);
  }
  file.close();
}

void setup()
{
  delay(1000);
  Serial.begin(115200);
  delay(1000);
  Serial.println("Xiao ESP32S3 Sense exercise");
  
  // Init Display
  if (!gfx->begin())
  {
    Serial.println("gfx->begin() failed!");
  }
  gfx->fillScreen(RGB565_BLACK);
  gfx->setTextSize(2);
  gfx->println(F("Xiao ESP32S3 Sense exercise"));

  pinMode(GFX_BL, OUTPUT);
  digitalWrite(GFX_BL, HIGH);

  if (!SD.begin(SD_CS))
  {
    Serial.println(F("ERROR: File System Mount Failed!"));
    gfx->println(F("ERROR: File System Mount Failed!"));

    for(;;); // Fatal error, do not continue
  }
  else
  {
    Serial.println(F("File System Mount Successful!"));
    gfx->println(F("File System Mount Successful!"));
  }

  uint8_t cardType = SD.cardType();

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

  uint64_t cardSize = SD.cardSize() / (1024 * 1024);
  Serial.printf("SD Card Size: %lluMB\r\n", cardSize);
  gfx->printf("SD Card Size: %lluMB\r\n", cardSize);

  uint64_t totalBytes = SD.totalBytes();
  uint64_t usedBytes = SD.usedBytes();
  Serial.printf("SD.totalBytes = %lld \r\n", totalBytes);
  gfx->printf("SD.totalBytes = %lld \r\n", totalBytes);
  Serial.printf("SD.usedBytes = %lld \r\n", usedBytes);
  gfx->printf("SD.usedBytes = %lld \r\n", usedBytes);

  delay(2000);

  // Read and display /hello.txt on SD
  Serial.println();
  gfx->println();
  readFile(SD, "/hello.txt");
}

void loop() {
}





XiaoS3_ST7789_SD_listDir.ino, list files in SD /images_240 directory.
/*******************************************************************************
Xiao ESP32S3 Sense exercise
List files in SD /images_240 directory.
 ******************************************************************************/

/*******************************************************************************
 * Start of Arduino_GFX setting
 ******************************************************************************/
 #include <Arduino_GFX_Library.h>
//=== Custom to match my connection ===========================================

#define PIN_BLK 4
#define PIN_CS  3
#define PIN_DC  2
#define PIN_RES 1
#define PIN_SDA 9
#define PIN_SCL 7

#define GFX_BL PIN_BLK

#define CTP_INT 43
#define CTP_RST 44

#define FT6236_ADDR 0x38

#define DISP_WIDTH 240
#define DISP_HEIGHT 240

Arduino_DataBus *bus = new Arduino_HWSPI(PIN_DC, PIN_CS);
Arduino_GFX *gfx = new Arduino_ST7789(bus, PIN_RES, 0 /* rotation */, true /* IPS */, DISP_WIDTH, DISP_HEIGHT);
/*******************************************************************************
 * End of Arduino_GFX setting
 ******************************************************************************/

// SD
#include <SD.h>
#define SD_CS         21

void readFile(fs::FS &fs, const char *path) {
  Serial.printf("Reading file: %s\n", path);
  gfx->printf("Reading file: %s\n", path);

  File file = fs.open(path);
  if (!file) {
    Serial.println("Failed to open file for reading");
    gfx->println("Failed to open file for reading");
    return;
  }
  Serial.print("Read from file: ");
  while (file.available()) {
    char c = file.read();
    Serial.write(c);
    gfx->write(c);
  }
  file.close();
}

void listDir(fs::FS &fs, const char * dirname){
  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();
  while(file){
    if(file.isDirectory()){
      Serial.print("  DIR : ");
      Serial.println(file.name());
    } else {
      Serial.print("  FILE: ");
      Serial.print(file.name());
      gfx->println(file.name());
      Serial.print("  SIZE: ");
      Serial.println(file.size());
    }
    file = root.openNextFile();
  }
}

void setup()
{
  delay(1000);
  Serial.begin(115200);
  delay(1000);
  Serial.println("Xiao ESP32S3 Sense exercise");
  
  // Init Display
  if (!gfx->begin())
  {
    Serial.println("gfx->begin() failed!");
  }
  gfx->fillScreen(RGB565_BLACK);
  gfx->setTextSize(2);
  gfx->println(F("Xiao ESP32S3 Sense exercise"));

  pinMode(GFX_BL, OUTPUT);
  digitalWrite(GFX_BL, HIGH);

  if (!SD.begin(SD_CS))
  {
    Serial.println(F("ERROR: File System Mount Failed!"));
    gfx->println(F("ERROR: File System Mount Failed!"));

    for(;;); // Fatal error, do not continue
  }
  else
  {
    Serial.println(F("File System Mount Successful!"));
    gfx->println(F("File System Mount Successful!"));
  }

  uint8_t cardType = SD.cardType();

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

  uint64_t cardSize = SD.cardSize() / (1024 * 1024);
  Serial.printf("SD Card Size: %lluMB\r\n", cardSize);
  gfx->printf("SD Card Size: %lluMB\r\n", cardSize);

  uint64_t totalBytes = SD.totalBytes();
  uint64_t usedBytes = SD.usedBytes();
  Serial.printf("SD.totalBytes = %lld \r\n", totalBytes);
  gfx->printf("SD.totalBytes = %lld \r\n", totalBytes);
  Serial.printf("SD.usedBytes = %lld \r\n", usedBytes);
  gfx->printf("SD.usedBytes = %lld \r\n", usedBytes);

  delay(2000);

  Serial.println();
  gfx->fillScreen(RGB565_BLACK);
  gfx->setCursor(0, 0);
  listDir(SD, "/images_240");
}

void loop() {
}






List files in SD images_240 directory on LVGL list:



XiaoS3_ST7789_SD_listFiles_in_lvgl.ino
/*******************************************************************************
Xiao ESP32S3 Sense exercise
List files in SD /images_240 directory.
 ******************************************************************************/

/*******************************************************************************
 * Start of Arduino_GFX setting
 ******************************************************************************/
 #include <Arduino_GFX_Library.h>
//=== Custom to match my connection ===========================================

#define PIN_BLK 4
#define PIN_CS  3
#define PIN_DC  2
#define PIN_RES 1
#define PIN_SDA 9
#define PIN_SCL 7

#define GFX_BL PIN_BLK

#define CTP_INT 43
#define CTP_RST 44

#define FT6236_ADDR 0x38

#define DISP_WIDTH 240
#define DISP_HEIGHT 240

Arduino_DataBus *bus = new Arduino_HWSPI(PIN_DC, PIN_CS);
Arduino_GFX *gfx = new Arduino_ST7789(bus, PIN_RES, 0 /* rotation */, true /* IPS */, DISP_WIDTH, DISP_HEIGHT);
/*******************************************************************************
 * End of Arduino_GFX setting
 ******************************************************************************/

// SD
#include <SD.h>
#define SD_CS         21

const char *images_path = "/images_240";
//==============================================================
// LVGL
#include <lvgl.h>
// for FT6236 cap touch
#include <Wire.h>

uint32_t screenWidth;
uint32_t screenHeight;
uint32_t bufSize;
lv_display_t *disp;
lv_color_t *disp_draw_buf;

static lv_obj_t * list1;

uint32_t millis_cb(void)
{
  return millis();
}

/* LVGL calls it when a rendered image needs to copied to the display*/
void my_disp_flush(lv_display_t *disp, const lv_area_t *area, uint8_t *px_map)
{
#ifndef DIRECT_RENDER_MODE
  uint32_t w = lv_area_get_width(area);
  uint32_t h = lv_area_get_height(area);

  gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)px_map, w, h);
#endif // #ifndef DIRECT_RENDER_MODE

  /*Call it to tell LVGL you are ready*/
  lv_disp_flush_ready(disp);
}

/*Read the touchpad*/
void my_touchpad_read( lv_indev_t * indev, lv_indev_data_t * data )
{
    if (get_touch_count()>0){
        data->state = LV_INDEV_STATE_PRESSED;

        int x, y;
        
        Wire.beginTransmission(FT6236_ADDR);
        Wire.write(0x03);
        Wire.endTransmission();
        Wire.requestFrom(FT6236_ADDR, 2);
        x = (Wire.read() & 0x0f) << 8 | Wire.read();
        x = DISP_WIDTH - x;
        
        Wire.beginTransmission(FT6236_ADDR);
        Wire.write(0x05);
        Wire.endTransmission();
        Wire.requestFrom(FT6236_ADDR, 2);
        y = (Wire.read() & 0x0f) << 8 | Wire.read();
        y = DISP_HEIGHT - y;

        data->point.x = x;
        data->point.y = y;

    }else{
        data->state = LV_INDEV_STATE_RELEASED;
    }
}

int get_touch_count(){
    // Register 0x02;
    // Touch count, max 2
    Wire.beginTransmission(FT6236_ADDR);
    Wire.write(0x02);
    Wire.endTransmission();
    Wire.requestFrom(FT6236_ADDR, 1);
    
    return(Wire.read());
}

//==============================================================
void readFile(fs::FS &fs, const char *path) {
  Serial.printf("Reading file: %s\n", path);

  File file = fs.open(path);
  if (!file) {
    Serial.println("Failed to open file for reading");
    return;
  }
  Serial.print("Read from file: ");
  while (file.available()) {
    char c = file.read();
    Serial.write(c);
    gfx->write(c);
  }
  file.close();
}

void listDir(fs::FS &fs, const char * dirname){
  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();
  while(file){
    if(file.isDirectory()){
      Serial.print("  DIR : ");
      Serial.println(file.name());
    } else {
      Serial.print("  FILE: ");
      Serial.print(file.name());
      lv_list_add_text(list1, file.name());
      Serial.print("  SIZE: ");
      Serial.println(file.size());
    }
    file = root.openNextFile();
  }
}

void setup()
{
  delay(1000);
  Serial.begin(115200);
  delay(1000);
  Serial.println("Xiao ESP32S3 Sense exercise");
  
  // Init Display
  if (!gfx->begin())
  {
    Serial.println("gfx->begin() failed!");
  }
  gfx->fillScreen(RGB565_BLACK);

  // Init I2C for FT6236 and CTR_RST
  Wire.begin();   // I2C
  delay(100);
  pinMode(CTP_RST, OUTPUT);
  digitalWrite(CTP_RST, HIGH);
  delay(100);
  digitalWrite(CTP_RST, LOW);
  delay(100);
  digitalWrite(CTP_RST, HIGH);
  delay(100);

//====================================================================
// init LVGL
  lv_init();

  /*Set a tick source so that LVGL will know how much time elapsed. */
  lv_tick_set_cb(millis_cb);

  screenWidth = gfx->width();
  screenHeight = gfx->height();

#ifdef DIRECT_RENDER_MODE
  bufSize = screenWidth * screenHeight;
#else
  bufSize = screenWidth * 40;
#endif

#if defined(DIRECT_RENDER_MODE) && (defined(CANVAS) || defined(RGB_PANEL) || defined(DSI_PANEL))
  disp_draw_buf = (lv_color_t *)gfx->getFramebuffer();
#else  // !(defined(DIRECT_RENDER_MODE) && (defined(CANVAS) || defined(RGB_PANEL) || defined(DSI_PANEL)))
  disp_draw_buf = (lv_color_t *)heap_caps_malloc(bufSize * 2, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
  if (!disp_draw_buf)
  {
    // remove MALLOC_CAP_INTERNAL flag try again
    disp_draw_buf = (lv_color_t *)heap_caps_malloc(bufSize * 2, MALLOC_CAP_8BIT);
  }
#endif // !(defined(DIRECT_RENDER_MODE) && (defined(CANVAS) || defined(RGB_PANEL) || defined(DSI_PANEL)))



  if (!disp_draw_buf)
  {
    Serial.println("LVGL disp_draw_buf allocate failed!");
  }
  else
  {
    disp = lv_display_create(screenWidth, screenHeight);
    lv_display_set_flush_cb(disp, my_disp_flush);
#ifdef DIRECT_RENDER_MODE
    lv_display_set_buffers(disp, disp_draw_buf, NULL, bufSize * 2, LV_DISPLAY_RENDER_MODE_DIRECT);
#else
    lv_display_set_buffers(disp, disp_draw_buf, NULL, bufSize * 2, LV_DISPLAY_RENDER_MODE_PARTIAL);
#endif

    /*Initialize the (dummy) input device driver*/
    lv_indev_t *indev = lv_indev_create();
    lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER); /*Touchpad should have POINTER type*/
    lv_indev_set_read_cb(indev, my_touchpad_read);
  }

//====================================================================
// Create LVGL content

  lv_obj_t *label_top = lv_label_create(lv_screen_active());
  lv_label_set_text(label_top, images_path);
  lv_obj_align(label_top, LV_ALIGN_TOP_LEFT, 0, 0);

  lv_obj_t *label_bottom = lv_label_create(lv_screen_active());
  lv_label_set_text(label_bottom, "coXXect.blogspot.com");
  lv_obj_align(label_bottom, LV_ALIGN_BOTTOM_MID, 0, 0);

  /*Create a list*/
  list1 = lv_list_create(lv_screen_active());
  lv_obj_set_size(list1, 200, 200);
  lv_obj_center(list1);


//====================================================================
  pinMode(GFX_BL, OUTPUT);
  digitalWrite(GFX_BL, HIGH);

  if (!SD.begin(SD_CS))
  {
    Serial.println(F("ERROR: File System Mount Failed!"));

    for(;;); // Fatal error, do not continue
  }
  else
  {
    Serial.println(F("File System Mount Successful!"));
  }

  uint8_t cardType = SD.cardType();

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

  uint64_t cardSize = SD.cardSize() / (1024 * 1024);
  Serial.printf("SD Card Size: %lluMB\r\n", cardSize);

  uint64_t totalBytes = SD.totalBytes();
  uint64_t usedBytes = SD.usedBytes();
  Serial.printf("SD.totalBytes = %lld \r\n", totalBytes);
  Serial.printf("SD.usedBytes = %lld \r\n", usedBytes);

  listDir(SD, images_path);
}

void loop() {
  lv_task_handler(); /* let the GUI do its work */

#ifdef DIRECT_RENDER_MODE
#if defined(CANVAS) || defined(RGB_PANEL) || defined(DSI_PANEL)
  gfx->flush();
#else // !(defined(CANVAS) || defined(RGB_PANEL) || defined(DSI_PANEL))
  gfx->draw16bitRGBBitmap(0, 0, (uint16_t *)disp_draw_buf, screenWidth, screenHeight);
#endif // !(defined(CANVAS) || defined(RGB_PANEL) || defined(DSI_PANEL))
#else  // !DIRECT_RENDER_MODE
#ifdef CANVAS
  gfx->flush();
#endif
#endif // !DIRECT_RENDER_MODE

  delay(5);
}


Next:
ESP32S3 (Arduino framework) decode jpg and display on ST7789 SPI Display.

Comments

Popular posts from this blog

480x320 TFT/ILI9488 SPI wih EP32C3 (arduino-esp32) using Arduino_GFX Library

Drive 320x240 ILI9341 SPI TFT using ESP32-S3 (NodeMCU ESP-S3-12K-Kit) using TFT_eSPI library, in Arduino Framework.